文章目录
- 探讨内容目录
- 一个类的初始化
- 结果分析
- 两个类的初始化
- 结果分析
- 注意的地方
探讨内容目录
- 一个类的初始化顺序,由简至繁的讲解。
- 两个类的初始化,子类初始化的时候,父类是如何行动的。
一个类的初始化
- 这个类包含了普通变量,静态变量,普通代码块,静态代码块,构造器,以及普通方法。
public class OneClass {
//普通属性
public String a = "普通变量声明时候的值";
//静态属性
public static String staticB = "静态变量声明时候的值";
//代码块
{
System.out.println("此时此刻普通代码块: " + a);
a = "普通代码块中的值";
System.out.println("此时此刻普通代码块: " + staticB);
staticB = "静态代码在普通代码块中的值";
}
//静态代码块
static {
System.out.println("此时此刻静态代码块: " + staticB);
staticB = "静态代码在普通代码块中的值";
}
//构造方法
public OneClass(String a, String staticB){
this.a = a;
OneClass.staticB = staticB;
System.out.println("构造方法执行了");
}
@Override
public String toString() {
return "OneClass{" +
"a='" + a + '\'' +
"staticB='" + staticB + '\'' +
'}';
}
}
class Test{
public static void main(String[] args) {
String s = new OneClass("a", "staticB").toString();
System.out.println(s);
}
}
结果分析
毫无疑问,变量肯定是首先被初始化的(这个可以自己验证:写一个类,然后把该类作为另一个类的属性并且实例化),然后根据结果可查看到首先执行的是静态代码块,其次是普通代码块,接着是构造方法!构造方法中的初始化覆盖了前面两种代码块的值,所以最后打印输出各属性的值是用户传入的参数。
两个类的初始化
public class TwoClass {
public static void main(String[] args) {
String s = new Son().toString();
System.out.println(s);
}
}
class Father{
public String name = "nameDemo";
public static String nickName ="nickNameDemo";
//代码块
{
System.out.println("普通代码块:name: " + name);
System.out.println("普通代码块:nickName: " + nickName);
name = "叮当";
nickName = "小小";
}
static {
System.out.println("静态代码块:nickName: " + nickName);
nickName = "大大";
}
public Father(){
name = "bailixiang";
nickName = "wozhi";
A();
System.out.println(this);
System.out.println("father类的构造方法执行完毕");
}
public void A(){
System.out.println("father类的A()方法");
}
@Override
public String toString() {
return "Father{" +
"name='" + name + '\'' +
"nickName='" + nickName + '\'' +
'}';
}
}
class Son extends Father{
public static String nickName = "dd";
{
System.out.println("son中的普通代码块");
}
static {
System.out.println("son中的静态代码块: " + nickName);
nickName = "son_nickName";
}
public Son() {
System.out.println("son的构造方法");
}
@Override
public void A() {
System.out.println("子类中的A()方法");
}
@Override
public String toString() {
return "Son{" +
"name='" + name + '\'' +
"nickName='" + nickName + '\'' +
"super.nickName='" + super.nickName + '\'' +
'}';
}
}
结果分析
在类加载阶段,静态属性便已经别加载到方法区当中了,所以初始化一个子类的时候,首先便是执行父类和子类的静态代码块,接着便是父类中的普通构造代码块以及父类的构造方法,然后便是子类的普通构造代码块,最后是子类的构造方法!
注意的地方
- 父类构造方法调用了A() 方法,但是代码确实子类的实现,**System.out.println(this);**同理也是子类的实现,这是在继承体系当中需要特别注意的一点,尽量在构造方法当中不调用会被覆盖的方法。
- 关于静态属性,子类中的静态属性并不会覆盖掉父类中静态属性的值,他们只是存放在了不同的地方,程序默认调用子类的静态属性,如果需要显示的调用父类的静态属性的值,则必须使用super关键字进行显示的调用。