java初始化顺序,多态以及绑定

来源:互联网 发布:python 获取局域网ip 编辑:程序博客网 时间:2024/06/05 11:48

最近在思考类初始化的过程,经过查阅资料和实验也有了自己对初始化顺序的一些看法,在这里把他详细的写出来,希望对以后的自己还有同样有疑惑的人有帮助

先看一个例子:

class Father{int i =1;public Father(){show();}public void show(){System.out.println("fathwe"+i);}}class Son extends Father{int i=3;public void show(){System.out.println("son"+i);}}

public class Test2 {public static void main(String[] args) {// TODO Auto-generated method stubFather fa = new Son();System.out.println(fa.i);}}
答案:son0

会不会觉得奇怪?我列出执行的顺序,你再看看:

class Father{int i =1;                        //3public Father(){ show();                  //4}public void show(){System.out.println("fathwe"+i);}}class Son extends Father{int i=3;
<span style="white-space:pre"></span>public Son(){
<span style="white-space:pre"></span>super();}                  //2
<span style="font-size: 12px;">public void show(){                      </span>
System.out.println("son"+i);     //5}}

public class Test2 {public static void main(String[] args) {// TODO Auto-generated method stubFather fa = new Son();      //1}}

因为在子类中的  i  还没有附上 3 的值呢。所以最后的结果就是 0 啦。


那再把这整个过程的初始化顺序列出来:


1. 在Test中声明 Father 的 引用 fa ,所以就加载了 Father 的类,并且new Son();调用了 Son 的构造方法,则加载了        Son类并且执行构造方法。(在加载类的时候只是开辟了属性的一块内存,并给上默认值,数据类型为0,引用类型为        null)

2. 系统发现Son是继承Father类的(Son构造方法内super())就往上调用了Father的构造方法 生成父类Father的对象,在生成Father对象之前会把属性初始化(按照用户的设置赋值)

3. 再回去执行Son 的构造方法,在执行构造方法之前,又把Son的属性按照用户的设置对属性赋值。


ok,总结一下:

执行  父类  father = new 子类() 时,

会先加载父类(把属性第一次初始化,为0或null),

再加载子类(那属性第一次初始化,为0或null),

然后执行父类的构造方法(此前会把属性进行第二次初始化,根据用户设置的值),

再执行父类的构造方法(此前会把属性惊醒第二次初始化,根据用户设置的值。也就是说一个属性初始化分两步:1,加载类时为0或null  2.创建对象时为用户设置的值)。


所以也有一些结论:

  a。成员变量绑定的是引用的类型,方法绑定的是对象的类型(因为方法是后期绑定的(也叫动态绑定,或者运行时绑定),而属性在类编译时就绑定了,也叫前期绑定,所以方法具有多态,而属性不具有多态,所以方法能被覆盖,而属性不能被覆盖,)

再简单点说就是:方法看对象,属性看类型。


那下面思考一个问题:父类中的静态方法可以被重写吗?

表面上是可以的,但实际上这并属于java的重写,至于执行父类还是子类中的静态方法,完全取决于你使用父类类型的引用去调用,还是用子类类型的引用去调用。因为static静态的方法在类加载时就用类的类型绑定了,

----插入个知识:事实上构造方法也是默认静态的方法。而且private声明的方法也默认是final的。

(下一篇详细说一下:方法的绑定)

0 0