Java初始化问题

类加载机制



一、对于被static修饰的类变量

1.被final修饰。在准备阶段给类变量申请内存空间的同时就通过ConstantValue属性进行初始化,在调用此变量的时候,不会对此类进行初始化。

2.未被final修饰。在初始化阶段进行了初始化,通过类构造器<clinit>()方法进行初始化,只在类使用之前调用一次。

被动引用的情况:

<1> 通过子类调用父类的静态字段和静态方法时,只初始化父类,而不初始化子类。(不会执行子类构造器<clinit>()方法




结果:

<2>被final修饰的static变量,不会对此静态字段所属的类进行初始化。



<3>通过数组定义此类,不会触发此类的初始化


注:[[Lcn.hyy.test.classloading.SuperClass 此类代表一个元素类型为cn.hyy.test.classloading.SuperClass的二维数组,左边中括号的个数代表维数。

二、对于未被static修饰的实例变量

当初始化一个类时,若其父类还未初始化,则需要对其父类进行初始化。

1.通过new一个对象调用实例构造器<init>()方法。

   通过new关键字实例化对象时,既会调用实例构造方法<init>()方法,完成对对象的初始化。当子类之前未曾使用时,也会触发子类以及父类的初始化(执行子类和父类的类构造器<clinit>()方法)。



2.通过反射获得对象时,若类未进行初始化,会触发子类以及父类的初始化(执行子类和父类的类构造器<clinit>()方法)。



3.调用子类的静态字段和静态方法时,若类未进行初始化,会触发子类和父类的初始化(执行子类和父类的类构造器<clinit>()方法)。


三、类构造器<clinit>()方法与实例构造器<init>()方法

1.类构造器<clinit>()方法

由编译器自动收集类中所有类变量的赋值动作和静态语句块static{}中的语句合并产生的。

编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块只能访问到定义在静态语句块之前定义的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但不能访问。


2.实例构造器<init>()方法

由类的构造方法和{}语句块合并而成。

当未对类进行定义构造方法时,jdk会产生一个隐藏的无参构造方法,若此类有继承类,被继承的类也会有一个隐藏的无参构造方法,在子类的构造方法中会隐式调用super()来执行父类的无参构造方法。


猜你喜欢

转载自blog.csdn.net/yuyinghe0612/article/details/80217841