java学习-构造方法、静态、代码块

一、构造方法(封装)

  1构造方法的定义和使用

    Person p = new Person();

    1)构造方法:构造函数,构造器,Constructor

    2)构造方法的作用:

      为对象中的成员变量进行赋值,当创建对象同时,构造方法主动调用

等对象创建完毕,对象中的成员变量就有值了

    3)构造方法定义语法结构:

       修饰符 构造方法名(参数列表){

          方法体;// 通常使用构造进行成员变量的赋值

      }

    4)解释:

      1) 修饰符 : 通常使用public 公共的修饰

      2) 构造方法没有返回值类型, 连void都不写

      3) 构造方法名必须与类型保持一致,连大小写都必须一样

      4) 因为构造没有返回值类型,因此构造中可以没有return,  如果一定要写, return;

    5)构造方法的运行机制:

       每次创建对象, 构造方法会被JVM虚拟机主动调用一次, 构造方法不能被对象名.手动调用

举例

public class Person {
    // 定义出私有成员变量
    private String name;
    private int age;
    
    // 定义出一个构造,为了给成员变量进行赋值
    public Person() {
        name = "张三";
        age = 20;
        System.out.println("我是空参数构造,我执行了");
    }
public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }    
}
public class TestPerson {
    public static void main(String[] args) {
          // 1. 空参数构造的调用
          Person p = new Person();
          System.out.println(p.getName());
          System.out.println(p.getAge());
          
          // 构造方法无法被手动调用
          // p.Person();
          
          Person p1 = new Person();
          Person p2 = new Person();
    }
}

  2 构造方法使用的注意事项

  1. 构造方法的参数列表:

    1) 构造方法可以没有参数, 创建对象同时,()中就是空的, 只能在构造方法中给成员变量赋值默认值

    2) 构造方法可以有参数, 创建对象同时, ()中需要提供构造实际参数, 可以通过参数列表给成员变量进行赋值

  2.如果类中,没有定义任何的构造方法,那么系统自动为类型创建出一个空参数的构造方法,空参数构造使用 public修饰, 构造方法中,没有任何逻辑  

  3.如果类中, 已经手动定义了构造方法(不论构造有无参数列表), 那么系统不会自动添加任何构造

  4.构造方法可以重载:

   定义在同一个类中, 方法名相同, 方法的参数列表不同, 与方法的返回值类型无关,多个方法之间,称为方法重载(Overload)

    1) 构造方法名全部与类名一致, 方法名相同

    2) 方法的参数列表不同 : 自己把握

    3) 与方法的返回值类型无关 : 构造方法没有返回值类型

代码

public class Person {
    // 定义出私有成员变量
    private String name;
    private int age;
    
    // 定义出一个构造,为了给成员变量进行赋值
    public Person() {
        name = "张三";
        age = 20;
        System.out.println("我是空参数构造,我执行了");
    }
    
    // 定义出一个构造,通过构造方法参数列表给成员变量进行赋值
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("我是有参数构造,执行了~~~~~~~~~~");
    }
    
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
public class TestPerson {
    public static void main(String[] args) {
          // 1. 空参数构造的调用
          //The constructor Person() is undefined
          Person p = new Person();
          System.out.println(p.getName());
          System.out.println(p.getAge());
          
          // 构造方法无法被手动调用
          // p.Person();
          
          Person p1 = new Person();
          Person p2 = new Person();
        
         // 2. 有参数构造调用,需要创建对象同时,传递实际参数
          Person  p3 = new Person("小花",19);
          System.out.println(p3.getName());
          System.out.println(p3.getAge());
          
          Person  p4 = new Person("QQ",17);
          System.out.println(p4.getName());
          System.out.println(p4.getAge());
        
          // 3. 如果类型中,没有定义任何的构造方法,那么系统自动为类型创建出一个空参数的构造方法
          // 空参数构造使用 public修饰, 构造方法中,没有任何逻辑
           Person p5 = new Person();
    }

  3.this关键字在构造方法中的使用

  1. 构造方法之间,可以互相调用

     使用this(被调用的构造实际参数) , 可以调用另外一个构造方法、

  2.this() 本类构造方法之间的调用 : 要求this()必须放在构造方法有效行第一行

  3.总结this关键字的使用

    1) this关键字用于区分成员变量和局部变量重名问题, 带有this关键字的变量表示成员变量的使用

    2) this() : 表示本类构造之间的调用, ()需要传递实际参数, this()必须在构造方法有效行第一行

代码

public class ThisAndCon {
    private String name;
    private int age;
    
    // 1. 定义出一个空参数构造
    public ThisAndCon() {
        System.out.println("空参数构造");
    }
    
    // 2. 定义出一个有参数构造
    public ThisAndCon(String name, int age) {
        // this()表示调用空参数构造
        // this();
        // this(name) : 表示有参数构造调用
        this("小美");//Constructor call must be the first statement in a constructor
        // this.name = name;
        this.age = age;
        System.out.println("有参构造执行了");
    }
    
    // 3. 定义出一个有参数构造
    public ThisAndCon(String name) {
        this.name = name;
        System.out.println("给name赋值");
    }    
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
public class TestThis关键字在构造中的使用 {
    public static void main(String[] args) {
        ThisAndCon tac = new ThisAndCon("小花",25);
        System.out.println(tac.getName());
        System.out.println(tac.getAge());
    }

  4.构造方法和set赋值比较

  构造方法无法取代set方法给成员变量赋值过程

  1.构造只能在创建对象同时,给对象中的成员变量进行一次赋值,无法通过构造改值

  2.set赋值 : 发生在创建对象之后, 使用对象名.调用set方法给对象中的成员变量进行赋值, 方法可以多次调用,每次调用都可以修改对象中成员变量的值

  5.创建对象给成员变量赋值的过程

  1. 创建一个对象时, 给这个对象的成员变量赋值,有3种方式:

    1) JVM虚拟机默认赋值

    2) 成员变量的显示赋值

    3) 构造方法赋值

  2.三种方式赋值过程:

    1) 首先将对象的成员变量加载进堆内存中, JVM虚拟机进行默认的赋初值动作

    2) 如果成员变量有显示赋值(定义成员变量时, 直接赋值). 显示赋值覆盖掉JVM虚拟机赋值

    3) 如果有构造方法赋值, 那么构造赋值覆盖掉显示赋值, 最终以构造赋值为标准

 代码

public class 对象创建成员赋值过程 {
     // 姓名
    String name;
     // 年龄 age的显示赋值,覆盖掉JVM默认赋值0
    int age = 20;
     // 性别 sex的显示赋值,覆盖掉JVM默认赋值null
    String sex = "男";
    
    // 定义出一个构造
    public 对象创建成员赋值过程() {
        // sex的构造赋值覆盖掉了 显示赋值
        sex = "nv";
    }
}
public class Test创建对象成员赋值过程 {
    public static void main(String[] args) {
        对象创建成员赋值过程 demo = new 对象创建成员赋值过程();
        System.out.println(demo.age);// 20
        System.out.println(demo.name);// null
        System.out.println(demo.sex);// nv
    }

二、静态static

  1 静态概念的引入

  没有静态场景:

     类型Student, 所有学生对象具有相同的属性值,就是schoolName = "第一中学", 发现问题 : 每一个对象都需要存储并且维护相同的属性值

     1) 相同的属性,在每一个对象中都存储,浪费内存

     2) 维护难度大,如果修改校名, 所有对象都需要修改校名

   有静态场景 :

     将所有对象相同属性,在类型中使用static静态关键字进行修饰, 使用静态修饰的成员存储在方法区中,可以被所有的对象所共有使用, 是静态所表现出的共享性

  2.静态的特点

  1.static : 关键字, 表示静态,静止的

  2.静态属于类, 不属于任何对象;

  3.静态优先于对象存在, 但是可以被对象共享使用

  4.静态成员使用方式:

    1) 类名.直接调用;  (最推荐)

    2) 使用 对象名.调用; (不推荐)

代码

public class StaticStudentTest {
    public static void main(String[] args) {
        Student s = new Student();
        //The static field Student.schoolName should be accessed in a static way
        //System.out.println(s.schoolName);// 第一中学
        System.out.println(Student.schoolName);
        
        // s.schoolName = "一中";
        Student.schoolName = "一中";
        
        Student s1 = new Student();
        System.out.println(s1.schoolName);// 一中     
    }

  3.静态使用的注意事项

  1. 静态方法中不能直接使用非静态(成员变量,非静态方法)
  2. 静态方法中,不能直接使用非静态成员变量

   静态成员跟着类先进入内存, 非静态成员变量,跟着对象的创建后进入到堆内存中,先进入内存中的方法,无法直接使用后进入到内存中的成员

  3.静态方法中, 不能直接调用非静态方法使用

   静态成员跟着类先进入内存, 非静态方法需要在创建对象之后才能使用,先进入内存中的方法,无法直接使用后进入到内存中的非静态方法

  4.静态方法中,不能使用this关键字

   this表示本类对象的引用, 需要先创建出对象, this才能引用, 而静态优先于对象存在, 因此不能直接使用this关键字

代码

public class Demo01_静态中不能使用非静态 {
    // 1. 成员变量,定义一个非静态成员
    int i = 10;

    public static void main(String[] args) {
        // 2. 静态方法中不能直接使用非静态成员变量
        // System.out.println(i);
        
        // 3. 可以通过创建对象,调用非静态成员
        Demo01_静态中不能使用非静态 demo = new Demo01_静态中不能使用非静态();
        System.out.println(demo.i);// 10
        
        // 4. 静态方法中不能直接调用非静态方法
        // eat();
        demo.eat();
        
        // 5. 因为静态优先于对象存在, 所以静态方法中, 不能直接使用this关键字
        // System.out.println(this.i);//Cannot use this in a static context
    }
    
    public void eat() {
        System.out.println("我在吃饭");
    }

  4.静态成员变量和非静态成员变量的区别

  1.所属不同:

    a : 静态成员变量 : 属于类

    b : 非静态成员变量 : 属于对象

  2.在内存中存储区域不同:

    a : 静态成员变量 : 跟着类存储在方法区中

    b : 非静态成员变量 : 跟着对象存储在堆内存中

  3.生命周期不同:

    a : 静态成员变量 : 跟着类进入方法区,存在了;当类从方法区消失(将类中的所有内容全部运行完毕), 静态成员消亡

    b : 非静态成员变量 : 创建对象时, 存在了; 当对象再也没有任何使用的地方, 非静态成员变量跟着对象消亡

  4.调用方法不同:

    a : 静态成员变量: 1) 类名.直接调用   2) 对象名.调用

    b : 非静态成员变量 : 对象名.调用

三、代码块

  1. 代码块 : 使用一对大括号包裹起来的一段代码, 将代码块放置到不同的位置, 具有不同的功能, 有不同运行机制
  2. 代码块的分类:

    1) 局部代码块

    2) 构造代码块

    3) 静态代码块

    4) 同步代码块(非常重要,多线程)

  1.局部代码块

  1. 格式 : 代码使用一对大括号包裹起来
  2. 位置 : 方法中
  3. 作用 : 限定 定义在局部代码块中的变量作用范围, 如果变量无法再使用,这个变量所占有的内存空间就会被释放回收, 减少变量在内存中占有的时间, 节省内存
  4. 注意:

    1) 局部代码块, 只限定 定义在局部代码块中的变量

    2) 定义在局部代码块之外的变量, 局部代码块对其没有影响效果

     举例 : 定义在局部代码块之外的变量i, 如果在局部代码块中修改值, 出了局部代码块之外,修改仍然生效

代码

public class Demo01_局部代码块 {
    public static void main(String[] args) {
        int i = 10;
        // 局部代码块: 限定定义在局部代码块中的变量使用范围
        {
            i = 99;// 赋值,不受代码块影响
            int y = 20;
            System.out.println(i + y);// 119
        }
        // y cannot be resolved to a variable
        // System.out.println(y); 超出了y的使用范围
        
        System.out.println(i);// 99
    }

  2.构造代码块

  1. 格式 : 代码使用一对大括号包裹起来
  2. 位置 : 类中方法外
  3. 作用 :

    1) 可以通过构造代码块给成员变量进行赋值(默认赋值)

    2) 如果多个构造方法都具有相同的处理逻辑,可以将相同的逻辑提升到构造代码块中实现和运行

  4.运行机制:

     每次创建对象时, JVM虚拟机主动调用构造代码块一次, 在构造方法执行之前调用

 代码

public class Demo02_构造代码块 {
    int i;
    // 构造代码块 : 给成员赋值
    {
        i = 10;
        System.out.println("构造代码块运行了");
        System.out.println("构造执行~~~~~~~");
    }
    
    public Demo02_构造代码块() {
        // System.out.println("构造执行~~~~~~~");
    }
    
    public Demo02_构造代码块(int i) {
        this.i = i;
        // System.out.println("构造执行~~~~~~~");
    }
    
    public static void main(String[] args) {
        Demo02_构造代码块 demo = new Demo02_构造代码块();
        System.out.println(demo.i);
        
        Demo02_构造代码块 demo1 = new Demo02_构造代码块(99);
    }

  3. 静态代码块(掌握)

  1. 格式 :

    static {

      代码;

    }

  2.位置 : 类中方法外

  3.作用 :

    1) 可以给静态成员变量进行赋值(默认值)

    2) 如果有代码功能, 在类进入内存时,就需要马上执行,并且只执行一次,那么代码可以设计在静态代码块中

  1. 运行机制:

  当类加载进入到方法区时(使用这个类时), JVM虚拟机主动调用一次静态代码块,与创建多少次对象,后续使用无关

  1. 代码块的运行顺序:

   静态代码块--->构造代码块--->构造方法

public class Demo03_静态代码块 {
    
    static int j;
    
    {
        System.out.println("构造代码块");
        
    }
    // 静态代码块
    static {
        // 1. 给静态成员变量赋值
        j = 99;
        System.out.println("静态代码块运行了");
    }
    
    public Demo03_静态代码块() {
        System.out.println("构造方法~~~~~~");
    }    
    
    public static void main(String[] args) {
        /*System.out.println(Demo03_静态代码块.j);// 99 
        System.out.println(Demo03_静态代码块.j);// 99 
       */    
        Demo03_静态代码块 demo1 = new Demo03_静态代码块();
        Demo03_静态代码块 demo2 = new Demo03_静态代码块();    
    }

猜你喜欢

转载自www.cnblogs.com/a595452248/p/13393976.html
今日推荐