今天为了搞清楚实例化一个对象时其属性等的实例化顺序,写了下面的例子来探究:
实例化一个C的对象,其中,A为其静态属性,B为其普通属性;D为C的父类,E为D的静态属性,F为D的普通属性;C中还包含了静态代码块和普通代码块。
package com.yawn;
public class Test3 {
public static void main(String[] args) {
System.out.println("-------第1次实例化-------");
new C();
System.out.println("-------第2次实例化-------");
new C();
}
}
class A {
public A(){
System.out.println("构造静态属性A");
}
}
class B {
public B(){
System.out.println("构造普通属性B");
}
}
class E {
public E(){
System.out.println("父类的静态属性E");
}
}
class F {
public F(){
System.out.println("父类的普通属性F");
}
}
class D {
static E e = new E();
F f = new F();
public D(){
System.out.println("构造父类D");
}
}
class C extends D{
/**
* 静态代码块先于构造器执行 普通块先于构造块 只执行一次
* 凡是静态的与对象无关,先于对象存在的; 凡是静态的都是共享的
*/
B b = new B();
static A a = new A();
{
System.out.println("普通代码块");
}
static {
System.out.println("静态代码块");
}
public C(){
System.out.println("构造函数C");
}
}
运行结果:
-------第1次实例化-------
父类的静态属性E
构造静态属性A
静态代码块
父类的普通属性F
构造父类D
构造普通属性B
普通代码块
构造函数C
-------第2次实例化-------
父类的普通属性F
构造父类D
构造普通属性B
普通代码块
构造函数C
结论(实例化顺序):
- 父类静态的属性
- 父类静态的代码块
- 子类静态的属性
- 子类静态的代码块
- 父类普通属性
- 父类普通代码块
- 父类构造函数
- 子类普通属性
- 子类普通代码块
- 子类构造函数
静态的东西只在第一次实例化的时候执行
原则:先静态后非静态、先父类后子类