王道训练营Java31期
Day02 (oop部分:加载类、加载类并创建对象、成员变量、静态代码块、默认构造方法、单参数构造方法)
package com.xy.java.day06.oop_block_by_xy.block12.static3;
/**
* @program: day06_javase_oop2_block
* @description: 静态代码块的执行
* @author: xj992adolphxy@163.com
* @create: 2021-04-04 16:51
**/
/**
* 静态代码块
* 位置:成员位置
* 语法:static{}
* 作用:加载类时执行,给静态成员变量赋值
*
* 记忆点1.特殊情况:静态代码块写在成员变量上面
* 不要这样写,面试官问就正常顺序说,自己写代码不这样写
*
* 记忆点2.静态代码块能不能给普通成员变量赋值
* 不能。
* (所谓普通成员变量,就是成员位置的单行成员变量赋值语句中的变量,不加表示静态的关键字static)
* 不要给自己造成记忆负担,以后不要说普通成员变量,就说成员变量
* 成员变量赋值语句,是类声明、创建对象之后,才会执行的
* 要创建对象
*
* 记忆点3.静态代码块中能不能写this关键字
* 不能。
* 首次加载类到方法区,只是初始化了静态变量
* 一个对象的创建完成3步:
* 1.加载类。这里执行静态代码块
* 2.执行成员位置语句。
* 3.执行构造方法
* 4.回到创建对象语句。这里产生能用this的对象名
*
* 记忆点4.静态代码块执行次数
* 一次程序的运行期间,只执行一次,不会重复执行
*
* 记忆点5.静态代码块和静态成员
* 1.都不能调用成员变量和成员方法
* 2.静态代码块用的地方不多,除非程序需要复杂初始化
* 3.规范:静态成员变量定义语句在前,静态代码块在后
* 4.成员位置的构造代码块,可以给静态成员赋值
* 5.(再次重申)静态代码块,不可以给普通成员变量赋值
* (静态代码块位置:成员位置附近,一般在静态变量赋值语句之后,位于类头上部位置)
* 6.静态代码块、构造代码块给同一个静态成员变量赋值:
* -->先执行静态代码块
* -->后执行构造代码块,这里是最终值
* 原因:
* 静态代码块在首次类加载时执行
* 构造代码块在类加载、对象创建过程中执行
* 一前一后
*/
public class Demo {
public static void main(String[] args) {
Dog.age = 10;
//Dog.age = 10;
//Dog.age = 10;
Dog d = new Dog(18);
Dog d2 = new Dog(18);
Dog d3 = new Dog(18);
Dog d4 = new Dog(18);
Dog d5 = new Dog(18);
System.out.println(Dog.age);
}
}
class Dog {
int a;
static int age = 1;
{
age = 29;
}
static {
age = 2;
//System.out.println(this.a);
//cannot be referenced from a static context
}
public Dog() {
System.out.println("构造函数调用");
}
public Dog(int age) {
Dog.age = age;//构造方法中,可以调用类的静态变量,并赋值
}
}
代码单步调试
第一步:打断点
包含main()方法的类中psvm中的第一行。一般main()方法中第一行都要设置断点
类中静态成员赋值行、静态代码块中第一行、每个构造方法中第一行。
第二步:调试
对每一步跳转说明跳转原因。每次点击蓝色向下箭头(单步跳入)
<1>执行Demo类中main()方法,执行第57行代码:
没有显式声明Dog类,直接调用Dog类静态成员变量age。
加载Dog类到JVM内存中,跳转到Dog类的空参数构造方法(默认构造方法),暂不执行构造,然后从类头开始向下找静态成员。
找到第1个静态成员变量赋值语句
切换到Debugger标签检查变量值变化:
有默认初始化,int类型age默认赋初值0
继续查找并执行静态成员变量(如果有),找到1个静态代码块:
代码块中
age赋值:对静态成员变量赋值
插曲:什么时候用this
(输出当前对象的成员变量a的值。这里还没有经过创建对象、成员变量赋值、构造方法,所以这里不能用this)
至此静态成员、静态代码块赋值语句执行结束,回到main()方法中刚才调用Dog类的语句:
Debugger标签中检查变量值变化:age是2,马上就会变成10
至此,调用类Dog的静态成员变量的赋值语句执行结束。进入下一行
创建Dog类对象d,调用对应参数构造方法。跳转到Dog类的单参数构造方法,但是暂时不执行。
跳到Dog类头
从上到下,执行成员变量、代码块
找到第1个成员位置语句:成员变量赋值语句,是声明没有赋值,默认赋初值0。没有体现在截图中
找到第2个成员位置语句:代码块(大括号包起来的部分),执行里面第1句。age赋值29
成员变量语句全部执行完,跳转到刚才没有执行的构造方法
执行这个构造方法。传入age参数18
构造方法中第1句:赋值Dog类的静态成员变量age,age从29变成18
至此构造方法执行结束。回到main()方法刚才创建类对象语句
继续执行之后的创建对象语句。之后的跳转类似。
本次调试主要意义:理解类加载、类加载之后创建对象、成员变量位置的代码块中可以修改静态成员变量
本次调试缺点:没有用断点体现构造方法的选择
后续要完成:对于单参数、多参数的创建对象语句,用断点截图体现出调用对应参数的构造方法or默认构造方法。