二 java类初始化和对象初始化
——快乐是会传染的
类的初始化和对象实例化,似乎是没有什么必然联系,也没有可比性!但是很多时候的面试问题都会混在一起对比!如果说有联系的话,那就是初始化的时机不同,先后顺序不同。
1、从一个面试题引入
public class Test { public Test() { System.out.println("构造函数"); } static{ System.out.println("静态初始化模块"); } public static void main(String[] args) { Test t1 = new Test(); Test t2 = new Test(); } }
代码比较简单,运行结果是什么呢?为什么呢?
运行结果:
静态初始化模块
构造函数
构造函数
结果并不重要,或许都看过类似面试题!但是为什么呢?先简述几个知识点
2、类的初始化--简述
类加载:把class文件读入内存,并生成java.lang.Class对象
连接:验证,准备,解析。
类初始化:主要对类变量(static修饰)进行初始化。
3、类初始化时机
创建类实例。比如通过new 创建对象或通过反射创建对象(创建对象不仅类得到实例化,而且对象也会被实例化)。
调用某个类的静态方法 或 操作静态属性(static修饰的)。比如上例中在main方法中调用Test.a
使用反射创建某个类的Class帝乡,比如上例中:Class<Test> c= Test.class 或者 Class<Test> c = Class.forName("Test");此时对象并未初始化,只是类初始化。
某个类被初始化时,它的父类将先被初始化。
运行main(主类)方法时。
4、对象实例化。通过new创建对象或通过反射
对象实例化,会调用对象的构造函数去创建对象,并返回对象引用。
如:Test t = new Test(); // 调用构造方法,返回引用赋值给t
5、分析:
执行 Test t1 = new Test(); 创建t1对象时,首先进行类初始化,输出:"静态初始化模块",然后对象初始化,输出:"构造函数"
执行 Test t2 = new Test(); 创建t2对象时,首先检查类是否初始化。以为类已经初始化过,所以不会再初始化。而t1与t2是不同的对象,所以t2初始化,再次输出:“构造函数”
6、类或者对象的初始化,会首先检查父类是否已经初始化,如果没有初始化,则先初始化父类。所以java.lang.Object会首先被初始化(它默认是所有类的父类,如果没有显示指出父类)
7、问题扩展:为Test类添加一个父类,代码如下
public class TestParent { public TestParent() { System.out.println("TestParent构造函数"); } static{ System.out.println("TestParent静态方法"); } } public class Test extends TestParent{ public Test() { System.out.println("Test构造函数"); } static{ System.out.println("Test静态初始化模块"); } public static void main(String[] args) throws Exception { Test t1 = new Test(); Test t2 = new Test(); } }
运行结果(初始化首先检查和初始化父类,如果父类还有父类,依次执行):
TestParent静态方法
Test静态初始化模块
TestParent构造函数
Test构造函数
TestParent构造函数
Test构造函数
时间:2016年1月14日09:10:18