关于 Java 中类的初始化顺序的问题

突然思考到这个问题,就想做点实验理清楚一下。

1. 单个类的初始化

class Foo {
    static {
        // [1]
    }
    
    static Foo2 obj = new Foo2(); // [3]
    
    Foo2 obj2 = new Foo2(); // [4]
    
    public Foo() {
        // [5]
    }
}

class Foo2 {
    static {
        // [2]
    }
}

如上面代码所示,加载顺序如备注标记的一样。

  1. 先加载这个类的 static 代码块
  2. 加载 Foo2 的 static 代码块(因为要初始化 Foo 的静态成员 obj)
  3. 再加载 static 成员变量 obj
  4. 再加载普通成员变量 obj2
  5. 最后执行构造方法

这里需要注意的是,如果对象 obj 初始化为 null,则不会执行 [2] 的位置。

class Foo {
    static {
        // [1]
    }
    
    static Foo2 obj = null;
    
    Foo2 obj2 = null; 
    
    public Foo() {
        // [2]
    }
}

class Foo2 {
    
}

如上面代码所示,如果成员变量都被赋值为 null,则不会调用类的初始化逻辑。

2. 继承关系中类的初始化

在继承关系中,不过是先执行父类的初始化,再执行子类的初始化。

但这也就会发生一个怪事(面试点),在执行父类初始化的时候,读取子类的成员变量,自然就会出现 null 了。

比如下面这个例子:

class Animal {
    private String name = "Animal";
    
    public Animal() {
        print();
    }
    
    public void print() {
        System.out.println(name);
    }
}

class Dog extends Animal {
    private String name = "Dog";
    
    public void print() {
        System.out.println(name);
    }
}

public void static main(String[] args) {
    Animal a = new Dog();
}

请问输出是什么?

答案是:null

为什么呢?

首先记住大原则就好了,先执行父类的初始化,再执行子类的初始化。

我在代码上加上执行标记。

class Animal {
    // [2] 执行 Animal 的 static block,可惜没有

    private String name = "Animal"; // [3] 执行父类的成员变量初始化
    
    public Animal() { 
        // [4] 执行构造函数
        print();
    }
    
    public void print() {
        System.out.println(name);
    }
}

class Dog extends Animal {
    // [3] 执行 Animal 的 static block,可惜没有

    private String name = "Dog";
    
    public void print() {
        // [5] 这个方法 override 了父类的,所以执行这个 print
        // 由于 Dog.name 没有初始化,所以是null
        System.out.println(name);
    }
}

public void static main(String[] args) {
    Animal a = new Dog(); // [1] 先执行这里
}

需要额外注意的地方是:

  • 父类和子类都定义了 name ,它的修饰符是 private,因此这两个是独立的变量,没有任何关联。
  • print 方法是 public 的,因此在集成关系上有 override 的关系(有些情况下不加 @Override 注解被认为不是 override,因此规范起见,最好加上 @Override)

原文 

https://segmentfault.com/a/1190000022112064

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 关于 Java 中类的初始化顺序的问题

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址