类初始化
类初始化顺序
类初始化实例
父类定义
package com.phycanva.demonstrate;
public class Father_init{
private int i = test(); //非静态变量显式赋值
private static int j = method(); //静态变量显式赋值
static { //静态代码块
System.out.println("父类静态代码块");
}
Father_init(){ //构造器
System.out.println("父类构造器");
}
{ //非静态代码块
System.out.println("父类非静态代码块");
}
public int test(){
System.out.println("父类非静态变量显式赋值");
return 1;
}
public static int method(){
System.out.println("父类静态变量显式赋值");
return 1;
}
}
子类定义
package com.phycanva.demonstrate;
public class Son_init extends Father_init{
private int i = test(); //非静态变量显式赋值
private static int j = method(); //静态变量显式赋值
static { //静态代码块
System.out.println("子类静态代码块");
}
Son_init(){ //构造器
System.out.println("子类构造器");
}
{ //非静态代码块
System.out.println("子类非静态代码块");
}
public int test(){
System.out.println("子类非静态变量显式赋值");
return 1;
}
public static int method(){
System.out.println("子类静态变量显式赋值");
return 1;
}
public static void main(String[] args) {
}
}
在main函数里没有进行任何实例化操作,所有的类初始化的动作,都会被反映在标准输出中
运行结果:
父类静态变量显式赋值
父类静态代码块
子类静态变量显式赋值
子类静态代码块
小结
类初始化从main函数所在类开始,以下行为会触发类初始化:
(1)创建类的实例。为某个类创建实例的方式包括:使用new操作符来创建实例,通过反射来创建实例,通过反序列化的方式来创建实例。
(2)调用某个类的类方法(静态方法)。
(3)访问某个类变量或为某个类变量。或为该变量赋值
(4)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象。例如:Class,forName(“Person”),如果系统还未初始化Person类,则先初 始化Person类,然后返回Person类对应的java.lang.Class对象。
(5)初始化某个类的子类。子类的父类都会被初始化。
(6)直接使用java.exe命令运行某个主类,主类先被初始化。
-----注意: 对于一个final型的类变量,如果该变量的值在编译期就可以确定下来,那么这个类变量相当于“宏变量”,java编译器会在编译时直接把这个类变量出现的地方全部替换为它的值。因此即使程序使用静态变量,也不会导致该类的初始化。如下代码将不会打印出静态初始化块
以上内容转载自Mr_Monkey95512 - 什么时候进行java类的初始化
类初始化可以理解为是“静态初始化”,执行的是“静态变量显式赋值代码”和“静态代码块”,它们内部遵循代码书写的先后顺序;此外,在继承关系中初始化遵循父→子顺序。
实例初始化
实例初始化顺序
实例初始化实例
代码在 类初始化实例 的基础上在main函数中增添实例化语句:
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("子类实例1");
Son_init s1 = new Son_init();
System.out.println("子类实例2");
Son_init s2 = new Son_init();
}
运行结果:
父类静态变量显式赋值
父类静态代码块
子类静态变量显式赋值
子类静态代码块
子类实例1
子类非静态变量显式赋值
父类非静态代码块
父类构造器
子类非静态变量显式赋值
子类非静态代码块
子类构造器
子类实例2
子类非静态变量显式赋值
父类非静态代码块
父类构造器
子类非静态变量显式赋值
子类非静态代码块
子类构造器
可以看到输出由三个部分组成:类初始化、实例1初始化、实例初始化2,且两个实例初始化结果相同,我们提取实例1初始化的结果:
子类实例1
子类非静态变量显式赋值
父类非静态代码块
父类构造器
子类非静态变量显式赋值
子类非静态代码块
子类构造器
在第二行中出现了“子类非静态变量显式赋值”,而非“父类非静态变量显式赋值”。这是因为在调用非静态方法的时候,我们传入的this指向的是一个子类的对象,此时调用的test()方法就是子类重写的test()。
小结
实例初始化可以理解为是“非静态初始化”,执行的是“非静态变量显式赋值代码”和“非静态代码块”,它们内部遵循代码书写的先后顺序,在以上代码执行结束后最后执行构造器;此外,在继承关系中初始化遵循父→子顺序,并且需要注意其覆写效应。
后记
由于仍处于学习阶段,文章中的内容很可能不够准确也不够全面。文中若有错误出现,敬请指出,一定虚心改正;有需要补充修改的地方,也请各位不吝赐教,十分乐意与大家交流学习。