类成员加载顺序
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的构造器");
}
}
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 class Box {
public static void main(String[] args) {
A ab = new B();
System.out.println("---");
ab = new B();
}
}
面试的时候遇到了这样一个问题:
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 ClassLoad {
public static void main(String[] args) {
B anotherB = new B(1);// 思考有参构造的输出结果
}
}
如上代码,当调用了子类B的有参构造时,父类的构造器先执行肯定是确定无疑,但是是执行哪个构造器呢?
执行结果如下:
执行结果中可以看到,当调用了子类B的有参构造时,父类A依然是执行了无参构造
,也就是说,如果子类构造器中未显式指定父类构造器,那么将会默认执行父类的无参构造,此时,如果你重载了一个父类的有参构造而没有指定无参构造,那么编译将不会通过!!
例如错误代码如下:
以上内容感谢作者:https://blog.csdn.net/u014745069/article/details/82655339
结论
父类的静态字段——>父类静态代码块——>子类静态字段——>子类静态代码块——>父类成员变量(非静态字段)——>父类非静态代码块——>父类(
无参
)构造器——>子类成员变量——>子类非静态代码块——>子类构造器
测试
class A {
private static A a = new A();
static {
System.out.print("static");
}
public A() {
System.out.print("A");
}
}
public class B extends A {
public B() {
System.out.print("B");
}
public static void main(String[] args) {
B b = new B();
}
}
答案:AstaticAB
class A1 {
private static A1 a = new A1();
static {
System.out.print("static");
}
{
System.out.print("A");
}
}
public class B1 extends A1 {
public B1() {
System.out.print("B");
}
public static void main(String[] args) {
B1 b = new B1();
}
}
答案:AstaticAB
class A2 {
public A2() {
System.out.print("A gouzhao");
}
private static A2 a = new A2();
static {
System.out.print("static");
}
{
System.out.print("A1");
}
}
public class B2 extends A2 {
public B2() {
System.out.print("B");
}
public static void main(String[] args) {
System.out.println("0000");
B2 b = new B2();
}
}
答案:
A1A gouzhaostatic0000
A1A gouzhaoB
main方法是一个特殊的方法,在程序开始运行时,系统会找到main方法所在的那个class文件,然后把main方法的自代码装入内存,装入的过程其实就是初识化这个类的过程,初识化成员变量,初始化static变量,初始化static块,加载这个类(初始化)过程中如果不在执行的方法中new对象的话是不会执行其对应的构造方法和构造块的,但是这个题在初始化成员变量时就new对象了所以执行结果为那样。
在main方法中执行new B2时又去
执行了父类A2的构造代码块和无参
构造方法。