类的初始化过程
1)、具体操作
①静态成员变量的显式赋值代码
②执行静态代码块
2)、实质
编译器将这两部分代码在.class字节码文件中合为一个名<clinit>()的初始化方法
3)、执行顺序
在实例化方法执行之前,只执行一次:
①和②与其所定义的顺序有关
实例化过程
1)、具体操作
①成员变量显式赋值(有可能涉及到方法(重载问题))
②执行非静态代码块
③执行构造器
2)、实质
编译器会将这三部分代码在.class字节码文件中合为一个名<init>(形参列表)的实例化方法
每一个构造器都会对应一个实例化方法,即每次调用构造器都会调用相对应的<init>()方法
3)、执行顺序
在每次创建对象时执行:
③一定在最后执行,①和②与其所定义的顺序有关
两者基本执行顺序、
①先完成父类的类初始化
②再完成子类的类初始化
③父类的实例初始化
④子类的实例初始化
实例
测试父类
/*** 测试父类* @author 81493**/class Fa{//静态属性、代码块(类的初始化)static {System.out.println("(1)父类的静态代码块1");}public static String aa = staTest();static{System.out.println("(2)父类的静态代码块2");}//非静态属性、代码块(类的实例化){System.out.println("(3)父类非静态代码块1"); }public String hh = this.test(); //由于此时建立的是子类对象,则被子类重写的方法覆盖 {System.out.println("(4)父类非静态代码块2"); }//父类构造器public Fa() {System.out.println("(5)父类构造方法");}//属性赋值所调用函数public String test() {System.out.println("(6)父类赋值函数");return "";}public static String staTest() {System.out.println("(7)父类静态赋值函数");return "";}}
测试子类
/*** 测试子类* @author 81493**/class So extends Fa{//静态属性、代码块(类的初始化)static {System.out.println("(8)子类的静态代码块1");}public static String aa = staTest();static{System.out.println("(9)子类的静态代码块2");} //非静态属性、代码块(类的实例化){System.out.println("(10)子类非静态代码块1"); }public String hh = this.test(); {System.out.println("(11)子类非静态代码块2"); }//子类构造器public So() {System.out.println("(12)子类构造方法");}//所调用函数public String test() {System.out.println("(13)子类赋值函数");return "";}public static String staTest() {System.out.println("(14)子类静态赋值函数");return "";}}
测试结果
Fa fa = new So();System.out.println(fa);System.out.println("----------------------------");Fa fa2 = new So();System.out.println(fa2);
特殊情况(类中属性包含类本身的对象)
在类的初始化过程中会先执行类的实例化(<init>方法):
public class TestClassinit {//类本身的引用对象public static TestClassinit test = new TestClassinit();static {System.out.println("类的静态初始化");}{System.out.println("类的非静态代码块");}private TestClassinit(){System.out.println("类的构造方法");}public static void main(String[] args) {//执行main方法,该类必须初始化} }
结果:
其它情况
定义顺序
若将(静态)属性(attribute) 在(非)静态代码块之后定义,且(非)静态代码块中使用了该属性
则不能直接使用 attribute++,可以使用 attribute =value
但可使用 this.attribute++ 或 ClassName.attribute++(静态)来进行自增
就近原则
父类和子类定义相同的私有属性
①若子类无get/set方法但父类有,则子类中继承的set/get方法与父类属性绑定
②若子类有get/set方法且父类有,则子类中set/get方法将父类所继承的掩盖(重写),即与子类属性绑定