对象初始化的时候究竟是怎么个什么过程,static修饰的变量和方法都怎么回事?使用的时候有什么区别?
今天本小白带着疑问也进行了一番测试,。
先上代码(自己测试的时候直接copy就行):
class SuperClass {
static Print staticMember = new Print("父类static成员变量 1");
{
System.out.println("父类初始化块 1");
}
static {
System.out.println("父类static代码块 1");
}
Print commonMember = new Print("父类成员变量 1");
static Print staticMember1 = new Print("父类static成员变量 2");
static {
System.out.println("父类static代码块 2");
}
Print commonMember2 = new Print("父类成员变量 2");
{
System.out.println("父类初始化块 2");
}
SuperClass() {
System.out.println("父类构造函数()");
}
static void method() {
System.out.println("我是父类的一个静态方法 ");
}
void print() {
System.out.println("我是父类的一个方法");
}
}
class ChildClass extends SuperClass {
static Print childStaticMember = new Print("子类static成员变量");
Print childCommonMember = new Print("子类成员变量");
static {
System.out.println("子类static代码块");
}
{
System.out.println("子类初始化块");
}
ChildClass() {
System.out.println("子类构造函数()");
}
static void method2() {
System.out.println("我是子类的一个静态方法");
}
void print2() {
System.out.println("我是子类的一个方法");
}
}
class Print {
Print(String process) {
System.out.println(process);
}
}
public class Test {
public static void main(String[] args) {
SuperClass superClass = new SuperClass();
System.out.println("。。一个卑微分隔符。。。。");
new ChildClass();
System.out.println("。。又一个卑微分隔符。。。。");
ChildClass childClass = new ChildClass();
System.out.println("。。双一个卑微分隔符。。。。");
superClass.print();
SuperClass.method();
superClass.method();
System.out.println("。。最后一个卑微分隔符。。。。");
childClass.print2();
ChildClass.method2();
childClass.method2();
}
}
这是跑的结果:
父类static成员变量 1
父类static代码块 1
父类static成员变量 2
父类static代码块 2
父类初始化块 1
父类成员变量 1
父类成员变量 2
父类初始化块 2
父类构造函数()
。。一个卑微分隔符。。。。
子类static成员变量
子类static代码块
父类初始化块 1
父类成员变量 1
父类成员变量 2
父类初始化块 2
父类构造函数()
子类成员变量
子类初始化块
子类构造函数()
。。又一个卑微分隔符。。。。
父类初始化块 1
父类成员变量 1
父类成员变量 2
父类初始化块 2
父类构造函数()
子类成员变量
子类初始化块
子类构造函数()
。。双一个卑微分隔符。。。。
我是父类的一个方法
我是父类的一个静态方法
我是父类的一个静态方法
。。最后一个卑微分隔符。。。。
我是子类的一个方法
我是子类的一个静态方法
我是子类的一个静态方法
分析(自己可以打断点,然后一步步调试):
一、先看第一段:
new了一个父对象。
看下结果
- static修饰的成员变量和static修饰的代码块在初始化的时候优先级一样,执行的顺序完全看在代码中的先后顺序。
- 成员变量和初始化块在初始化的时候优先级一样,执行的顺序完全看在代码中的先后顺序。
- 构造函数最后执行。经常我们使用带参数的构造函数的时候,使用的变量就是我们的成员变量。
二、再看第二段:
刚刚已经new了一个父对象,现在再new一个子对象。
- 先执行了子类的static修饰的对象。
- 又把父类的初始化块、成员变量和构造函数执行了一遍。
- 执行了子类的成员变量、初始化块和构造函数执行了一遍。
三、看完了一和二,那么问题来了,如果我们把这两个顺序颠倒一下,会是什么情况。
代码变成这样,把前两个new的对象交换一下,变成这样:
跑的结果是这样
跟第一次的不一样了啊。
原因就是,对于有父类的对象的第一次创建过程是这样的:
- 父类静态成员变量和静态代码块。
- 子类静态成员变量和静态代码块。
- 父类初始化代码块和父类成员变量。
- 父类构造函数。
- 子类初始化代码块和子类成员变量。
- 子类构造函数。
我们知道static修饰的变量,只会在类第一次使用的时候被加载,那么第二次再创建父类(子类也可以)的时候,就不会再加载一遍了,所以上面的结果只有父类初始化块、父类成员变量和父类构造函数被用了。以后的第三、第四、~第N次都会这样。
四、再看接下来的部分。
结果是:
也就是说被static修饰的静态方法,是可以在对象内使用,也可以用类名.使用。
我的理解是static一旦被加载,那么就属于这个类和全体对象共有,也就是一个公共的东西。谁都可以用。
再看这个:
我用对象加了个点不显示method2(),但是一旦我输入了一部分就会给出来提示。
我想这可能是用来提醒我,对于static修饰的方法,建议使用类名而不要使用对象。
以上纯属个人理解,如有错误,请指明,非常感谢。