例一
代码
class A {
private static int numA;
private int numA2;
static {
System.out.println("A的静态字段 : " + numA);
System.out.println("A的静态代码块");
}
{
System.out.println("A的成员变量 : " + numA2);
System.out.println("A的非静态代码块");
}
public A() {
System.out.println("A的构造器");
}
public A(int n) {
System.out.println("A的有参构造");
this.numA2 = n;
}
}
class B extends A {
private static int numB;
private int numB2;
static {
System.out.println("B的静态字段 : " + numB);
System.out.println("B的静态代码块");
}
{
System.out.println("B的成员变量 : " + numB2);
System.out.println("B的非静态代码块");
}
public B() {
System.out.println("B的构造器");
}
public B(int n) {
System.out.println("B的有参构造");
this.numB2 = n;
}
}
public class Box {
public static void main(String[] args) {
A a1 = new B();
System.out.println("---");
A a2 = new B(2);
}
}
输出
A的静态字段 : 0
A的静态代码块
B的静态字段 : 0
B的静态代码块
A的成员变量 : 0
A的非静态代码块
A的构造器
B的成员变量 : 0
B的非静态代码块
B的构造器
---
A的成员变量 : 0
A的非静态代码块
A的构造器
B的成员变量 : 0
B的非静态代码块
B的有参构造
分析
首先从main函数进入程序,类中的静态成员会被先加载,加载的时候,JVM首先将类中静态属性的声明和静态方法的声明加载到内存中(方法区中),然后将静态属性赋值,之后执行静态块中的代码。如果在类加载的时候遇到实例化的情况,首先加载普通属性的声明,然后普通方法的声明,之后是普通属性赋值,执行构造块代码,最后执行构造函数中的代码。如果有继承关系,父类优先于子类。如果子类构造器中未显式指定父类构造器,那么将会默认执行父类的无参构造,此时,如果你重载了一个父类的有参构造而没有指定无参构造,那么编译将不会通过!!
父类的静态字段—>父类静态代码块—>子类静态字段—>子类静态代码块—>
父类成员变量(非静态字段)—>父类非静态代码块—>父类构造器—>子类成员变量—>子类非静态代码块—>子类构造器
1.存在父类加载父类的静态字段numA—>(只声明还没有赋值,当前为默认值0)
2.父类静态代码块—>(输出“A的静态字段 : 0”,“A的静态代码块”)
3.子类静态字段numB—>(只声明还没有赋值,当前为默认值0)
4.子类静态代码块输出—> (输出“B的静态字段 : 0”,“B的静态代码块”)
5.父类成员变量numA2—>(只声明还没有赋值,当前为默认值0)
6.父类非静态代码块—> (输出“A的成员变量 : 0”,“A的非静态代码块”)
7.父类构造器—> (输出“A的构造器”)
8.子类成员变量numB2—>(只声明还没有赋值,当前为默认值0)
9.子类非静态代码块—> (输出“B的成员变量 : 0”,“B的非静态代码块”)
10.子类构造器—> (输出“B的构造器”)
11.a1实例化完成, (输出“—”)
12.父类的静态字段,父类静态代码块,子类静态字段,子类静态代码块已加载,加载父类成员变量numA2—>(只声明还没有赋值,当前为默认值0)
13.父类非静态代码块—> (输出“A的成员变量 : 0”,“A的非静态代码块”)
14.父类构造器—> (输出“A的构造器”)
15.子类成员变量numB2—>(只声明还没有赋值,当前为默认值0)
16.子类非静态代码块—> (输出“B的成员变量 : 0”,“B的非静态代码块”)
17.子类构造器—> (输出“B的有参构造”)
例二
public class Text {
public static int k = 0;
public static Text t1 = new Text("t1");
public static Text t2 = new Text("t2");
public static int i = print("i");
public static int n = 99;
public int j = print("j");
{
print("构造块");
}
static {
print("静态块");
}
public Text(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++i;
++n;
}
public static int print(String str) {
System.out.println((++k) + ":" + str + " i=" + i + " n=" + n);
++n;
return ++i;
}
public static void main(String args[]) {
Text t = new Text("init");
}
}
输出
1:j i=0 n=0
2:构造块 i=1 n=1
3:t1 i=2 n=2
4:j i=3 n=3
5:构造块 i=4 n=4
6:t2 i=5 n=5
7:i i=6 n=6
8:静态块 i=7 n=99
9:j i=8 n=100
10:构造块 i=9 n=101
11:init i=10 n=102
分析
- 加载静态 字段 k, t1, t2, i, n(只有声明还没有赋值),然后加载静态方法声明"static int print(String str) {}"。之后对静态属性赋值。
- 加载静态字段 k=0
- 加载静态字段"public static Text t1 = new Text(“t1”);"这是实例化的过程,这时类暂时不加载,实例化的情况,首先加载普通属性的声明,然后普通方法的声明,之后是普通属性赋值,执行构造块代码,最后执行构造函数中的代码。
3.1普通属性的声明,然后普通方法的声明后是普通属性赋值:j调用“public static int print(String str) {}”—> (输出“1:j i=0 n=0”)
3.2. 构造块代码调用“public static int print(String str) {}”—> (输出“2:构造块 i=1 n=1”)
3.3. 执行构造函数中的代码—> (输出“3:t1 i=2 n=2”) - 加载静态字段"public static Text t1 = new Text(“t1”);"这是实例化的过程,这时类暂时不加载,实例化的情况,首先加载普通属性的声明,然后普通方法的声明,之后是普通属性赋值,执行构造块代码,最后执行构造函数中的代码。
4.1. 普通属性的声明,然后普通方法的声明后是普通属性赋值:j调用“public static int print(String str) {}”—> (输出“4:j i=3 n=3”)
4.2. 构造块代码调用“public static int print(String str) {}”—> (输出“5:构造块 i=4 n=4”)
4.3. 执行构造函数中的代码—> (输出“6:t2 i=5 n=5”) - 加载静态字段 public static int i = print(“i”);—> (输出“7:i i=6 n=6”)
- 静态字段n赋值99
- 静态代码块—> (输出“8:静态块 i=7 n=99”)
- 成员变量" public int j = print(“j”);"—> (输出“9:j i=8 n=100”)
- 非静态代码块—> (输出“10:构造块 i=9 n=101”)
- 构造器 Text t = new Text(“init”);—> (输出“init i=10 n=102”)
例三
public class Father {
private int i=test();
private static int j=method();
static{
System.out.println("(1)");
}
public Father() {
System.out.println("(2)");
}
{
System.out.println("(3)");
}
public int test(){
System.out.println("(4)");
return 1;
}
public static int method(){
System.out.println("(5)");
return 1;
}
}
public class Son extends Father{
private int i=test();
private static int j=method();
static{
System.out.println("(6)");
}
Son(){
System.out.println("(7)");
}
{
System.out.println("(8)");
}
public int test(){
System.out.println("(9)");
return 1;
}
public static int method(){
System.out.println("(10)");
return 1;
}
public static void main(String[] args){
Son s1=new Son();
System.out.println("---");
Son s2=new Son();
}
}
输出
(5)
(1)
(10)
(6)
(9)
(3)
(2)
(9)
(8)
(7)
---
(9)
(3)
(2)
(9)
(8)
(7)
分析
this在构造器表示正在创建的对象,因为这里是在创建Son对象,所以test()执行的是子类重写对象
参考
https://www.cnblogs.com/ysocean/p/8194428.html
https://blog.csdn.net/u014745069/article/details/82655339
https://blog.csdn.net/iteye_6051/article/details/82647109