只要按照这个步骤,遇到这一类问题就可以解决了。
1. 类中所有属性的默认值(一举而成)
2. 父类静态属性初始化,静态块,静态方法的声明(按出现顺序执行)
3. 子类静态属性初始化,静态块,静态方法的声明 (按出现顺序执行)
4. 调用父类的构造方法,
首先父类的非静态成员初始化,构造块,普通方法的声明(按出现顺序执行)
然后父类构造方法
5. 调用子类的构造方法,
首先子类的非静态成员初始化,构造块,普通方法的声明(按出现顺序执行)
然后子类构造方法
说明: 1-3:类加载过程,不涉及构造方法
1-5: 实例化过程,涉及构造方法
参考问题:执行下列代码,输出是什么?
class A {
public A() {
System.out.println("A的构造方法");
}
public static int j = print();
public static int print() {
System.out.println("A print");
return 521;
}
}
public class Test1 extends A {
public Test1() {
System.out.println("Test1的构造方法");
}
public static int k = print();
public static int print() {
System.out.println("Test print");
return 522;
}
public static void main(String[] args) {
System.out.println("main start");
Test1 t1 = new Test1();
}
}
看看是不是这个?如果是那么执行顺序掌握的不错。
A print
Test print
main start
A的构造方法
Test1的构造方法
再来个上题加强版:问输出顺序是什么?
public class Test1 extends A {
public Test1() {
System.out.println("Test1的构造方法");
}
public static int k = print();
{
System.out.println(k);
}
public static int print() {
System.out.println("Test print");
return 522;
}
public static void main(String[] args) {
System.out.println("main start");
Test1 t1 = new Test1();
Test1 t3;
Test1 t2 = new Test1();
}
}
class A {
public A() {
System.out.println("A的构造方法");
}
{
System.out.println(j);
}
public static int j = print();
static {
System.out.println(j);
}
public static int print() {
System.out.println("A print");
return 521;
}
static{
System.out.println("A的static block");
}
}
看看输出是不是:
A print
521
A的static block
Test print
main start
521
A的构造方法
522
Test1的构造方法
521
A的构造方法
522
Test1的构造方法
重复输出的部分:
521
A的构造方法
522
Test1的构造方法
来自于第二次new过程中:运行父类构造体与构造方法->子类构造体与构造方法
而且也可以看出 类的申明不会调用类的构造体
上文转载自:https://www.cnblogs.com/greatfish/p/5771548.html
更新:
又看到一道类加载顺序题:https://blog.csdn.net/a352193394/article/details/7341015
这里修改成加强版,试试做不做得对。
问下面Test1运行输出什么?
public class Test1 {
static Singleton singleton = new Singleton();
public static void main(String[] args) {
Singleton s = singleton.getSingleton();
System.out.println("counter1 = "+s.counter1);
System.out.println("counter2 = "+s.counter2);
}
}
class Singleton{
private static Singleton singleton = new Singleton();
static {
System.out.println(singleton.counter1);
System.out.println(singleton.counter2);
}
public static int counter1;
public static int counter2 = 3;
public Singleton(){
counter1++;
counter2++;
}
public static Singleton getSingleton(){
return singleton;
}
}
说明:入口在Test1,Test1直接父类是java.lang.Object,那么开始模拟运行过程
先加载Test1父类Object,然后是Test1:
-
Test1 成员赋予默认值:
static singleton = null;
-
Test1 静态成员初始化
static Test1.singleton = new Singleton();调用了构造方法:
这一步内部执行顺序:1)先加载组合内部成员Singleton类:
成员赋予默认值,static Singleton.singleton =null,static Singleton.counter1 = 0,static Singleton.count2 = 0
初始化静态成员singleton,运行构造函数,static Singleton.counter1 = 1,static Singleton.counter2 = 1
执行static代码块:打印counter1的值1,换行,打印counter2的值1,换行
初始化静态类成员Singleton.counter2 = 3;
到此加载完毕,控制台已经输出1和1;此时static Singleton.counter1 = 1;static Singleton.counter 2 = 32)初始化组合成员类对象 static singleton = new Singleton()
这一步,调用构造方法后,static Singleton.counter 1 = 2,static Singleton.counter2 = 4
到此Test1静态成员初始化完毕,static Singleton.counter 1 = 2,static Singleton.counter2 = 4
然后运行Main
- 执行Main函数
1)Singleton s = singleton.getSingleton();
s指向自己的静态成员类的静态成员类singleton.singleton,后者指向2-1)中的Singleton实例(此时带有静态变量counter1=2,counter2=4)
2)打印counter1 = 2,换行
3)打印counter2 = 4,换行
运行验证与模拟结果一样:
1
1
counter1 = 2
counter2 = 4