Java语言基础:对象的初始化

发布时间:2011-3-29 19:49    发布者:1770309616
关键词: Java语言基础 , 对象的初始化
Java语言基础.pdf (205.39 KB)


1.  如果基类存在默认构造函数,则在子类构造之前,会先调用基类的默认构造函数:
view plaincopy to clipboardprint?
01.class A {   
02.    A() {   
03.        System.out.println("A create");   
04.    }   
05.}   
06.   
07.class B extends A {   
08.    B() {   
09.        // 会在这里先调用A的默认构造函数   
10.        System.out.println("B create");   
11.    }   
12.}   
13.   
14.class C extends A {   
15.    C(int i) {   
16.        // 会在这里先调用A的默认构造函数   
17.        System.out.println("C create");   
18.    }   
19.}   
20.   
21.public class Main {               
22.    public static void main(String[] args) {   
23.        B b = new B();   
24.        C c = new C(10);   
25.    }   26.}   
27.   
28.// 输出为:   
29.A create   
30.B create   3
1.A create   
32.C create  
class A {
    A() {
        System.out.println("A create");
    }
}

class B extends A {
    B() {
        // 会在这里先调用A的默认构造函数
        System.out.println("B create");
    }
}

class C extends A {
    C(int i) {
        // 会在这里先调用A的默认构造函数
        System.out.println("C create");
    }
}

public class Main {            
    public static void main(String[] args) {
        B b = new B();
        C c = new C(10);
    }
}

// 输出为:
A create
B create
A create
C create

2.  如果基类只有带参数的构造函数,子类必须在自己的构造函数中通过super(...)显式调用该基类构造函数:
view plaincopy to clipboardprint?
01.class A {   
02.    A(int i) {   
03.        System.out.println("A create");   
04.    }   
05.}   
06.   
07.class B extends A {   
08.    B() {   
09.        // 必须在这里显式调用父类的非默认构造函数,否则编译不通过   
10.        // 注意这调用只能放在最前面,否则编译不通过   
11.        super(20);   
12.        System.out.println("B create");   
13.    }   
14.}   
15.   
16.class C extends A {   
17.    C(int i) {   
18.        // 必须在这里显式调用父类的非默认构造函数,否则编译不通过   
19.        // 注意这调用只能放在最前面,否则编译不通过   
20.        super(30);   
21.        System.out.println("C create");   
22.    }   
23.}   
24.   
25.public class Main {               
26.    public static void main(String[] args) {   
27.        B b = new B();   
28.        C c = new C(10);   
29.    }   
30.}   
31.// 输出为:   
32.A create   
33.B create   
34.A create   
35.C create  
class A {
    A(int i) {
        System.out.println("A create");
    }
}

class B extends A {
    B() {
        // 必须在这里显式调用父类的非默认构造函数,否则编译不通过
        // 注意这调用只能放在最前面,否则编译不通过
        super(20);
        System.out.println("B create");
    }
}

class C extends A {
    C(int i) {
        // 必须在这里显式调用父类的非默认构造函数,否则编译不通过
        // 注意这调用只能放在最前面,否则编译不通过
        super(30);
        System.out.println("C create");
    }
}

public class Main {            
    public static void main(String[] args) {
        B b = new B();
        C c = new C(10);
    }
}
// 输出为:
A create
B create
A create
C create

3.  以上只讲了最简单的构造函数调用顺序,其实一个对象的真正的初始化过程应该是:
1.将对象的存储空间初始化为二进制的0.
2.先递归到最上层的基类去,将最上层的基类作为当前类。
3.对于当前类:
1.按声明顺序调用成员变量的初始设置代码。
2.调用构造函数。
4.接着将下一层继承类作为当前类,继续步骤3
先看下面的代码:
view plaincopy to clipboardprint?
01.class A {   
02.    A() {   
03.        System.out.println("A create");   
04.    }   
05.}   
06.   
07.class D {   
08.    D() {   
09.        System.out.println("D create");   
10.    }   
11.}   
12.   
13.class B extends A {   
14.    private D d = new D();   
15.    B() {   
16.        System.out.println("B create");   
17.    }   
18.}   
19.   
20.class C extends B {   
21.    C(int i) {   
22.        System.out.println("C create");   
23.    }   
24.}   
25.   
26.public class Main {               
27.    public static void main(String[] args) {   
28.        C c = new C(10);   
29.    }   
30.}  
class A {
    A() {
        System.out.println("A create");
    }
}

class D {
    D() {
        System.out.println("D create");
    }
}

class B extends A {
    private D d = new D();
    B() {
        System.out.println("B create");
    }
}

class C extends B {
    C(int i) {
        System.out.println("C create");
    }
}

public class Main {            
    public static void main(String[] args) {
        C c = new C(10);
    }
}

初始化过程大概是这样的:
1. 先从C递归到B,再从B递归到A。
2.A没有成员变量,所以A的构造函数被调用。
3.接到回到B,B有一个D类的成员有初始化,因此D的构造函数被调用。
4.接着B的构造函数被调用。
5.最后回到C,C的构造函数被调用。
所以输出应该是:
A create
D create
B create
C create

4.  必须小心在构造函数中调用虚函数(在JAVA里普通函数都是虚的)的隐患,特别是在基类的构造函数,因为此时继承类的成员可能还没有初始完毕:
view plaincopy to clipboardprint?
01.class A {   
02.    A() {   
03.        System.out.println("A create");   
04.        proc();   
05.    }   
06.    public void proc() {   
07.    }   
08.}   
09.   
10.class B extends A {   
11.    private int i;   
12.    B() {   
13.        System.out.println("B create");   
14.        i = 10;   
15.    }   
16.    public void proc(){   
17.        System.out.println(i);   
18.    }   
19.}   
20.   
21.public class Main {               
22.    public static void main(String[] args) {   
23.        B b = new B();   
24.    }   
25.}   
26.输出:   
27.A create   
28.0  
29.B create  
class A {
    A() {
        System.out.println("A create");
        proc();
    }
    public void proc() {
    }
}

class B extends A {
    private int i;
    B() {
        System.out.println("B create");
        i = 10;
    }
    public void proc(){
        System.out.println(i);
    }
}

public class Main {            
    public static void main(String[] args) {
        B b = new B();
    }
}
输出:
A create
0
B create
A的构造函数调用了proc,此时B的构造函数还没有被调用,因此i还没有被赋为10,最终输出结果是0。
5.  由于Java对象都是通过垃圾回收机制清理对象,因此Java的类没有析构函数,遇到需要清理类中资源的问题时,可以自己声明一个函数,如Dispose,在适当的时候调用之
本文地址:https://www.eechina.com/thread-60389-1-1.html     【打印本页】

本站部分文章为转载或网友发布,目的在于传递和分享信息,并不代表本网赞同其观点和对其真实性负责;文章版权归原作者及原出处所有,如涉及作品内容、版权和其它问题,我们将根据著作权人的要求,第一时间更正或删除。
您需要登录后才可以发表评论 登录 | 立即注册

厂商推荐

关于我们  -  服务条款  -  使用指南  -  站点地图  -  友情链接  -  联系我们
电子工程网 © 版权所有   京ICP备16069177号 | 京公网安备11010502021702
快速回复 返回顶部 返回列表