`
DoubleEO
  • 浏览: 154637 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

构造函数中调用其他的方法会产生的问题

 
阅读更多
看代码
class Base{
    private int val;
    //构造函数,调用lookup()方法
    Base() {
        val = lookup();
    }

    public int lookup() {
        return 5;
    }
    public int value(){
        return val;
    }
}
//子类,继承父类,并重写lookup()方法
class SubClass extends Base{
    private int num = 10;
    public int lookup(){
        return num;
    }
}
//测试一下
public class Test {
    public static void main(String[] args) {
        SubClass sc = new SubClass();
        System.out.println("sc.value()="+sc.value());
    }
}
打印结果:
sc.value()=0


结果很奇怪,会打印出0,分析了一下,造成原因是这样的:
1.初始化子类对象,会调用子类的构造器,子类的构造器的第一步就是调用父类的构造器,这个是自动隐式的写在了子类构造器的第一行(必须是第一行),原因肯定都知道了,因为子类继承了父类,父类的属性和方法会给子类一些,所以在子类初始化之前,先要保证父类初始化成功了。
2.现在调用到了父类的构造器,父类的构造器会调用lookup()方法
3.问题来了,这里会调用子类的lookup()方法
4.但是子类的num现在还没有初始化,是默认值0(类加载的时候通过内存清0,来实现实例变量的默认初始值),所以打印出0。
这种问题虽然很难碰到,但是如果碰到了,知道怎么回事,可以节省许多时间。

附上类初始化的顺序

引用
引用自: 臧圩人 
   1. 父类--静态变量
   2. 父类--静态初始化块
   3. 子类--静态变量
   4. 子类--静态初始化块
   5. 父类--变量
   6. 父类--初始化块
   7. 父类--构造器
   8. 子类--变量
   9. 子类--初始化块
  10. 子类--构造器
分享到:
评论
2 楼 eagleye 2009-01-16  
此例的执行过程应如下:
     base.Base()  //父类构造方法
    sc.lookup()
    base.value()
1 楼 unsid 2009-01-15  
构造函数不能调用可被子类复写的方法,构造函数不能创建新线程
前者有可能导致程序初始化不完整,后者可能导致互相等待初始化而死锁

相关推荐

    构造函数的继承问题 笔记

    子类如果有多个构造函数的时候,父类要么没有构造函数, 让编译器自动产生,那么在执行子类构造函数之前先执行编 译器自动产生的父类的缺省构造函数;...式的缺省构造函数可以让子类的构造函数调用。

    C# 构造函数如何调用虚方法

    在C#中,用virtual关键字修饰的方法(属性、事件)称为虚方法(属性、事件),表示该方法可以由派生类重写(override)。虚方法是.NET中的重要概念,可以说在某种程度上,虚方法使得多态成为可能。 然而虚方法的使用...

    CPP杂记——移动构造函数中需要注意的问题

    在多次使用传值做参数的方法时,不可避免的会产生临时对象从而调用拷贝构造函数。 . 默认的浅拷贝构造函数在临时变量被析构时还会释放其中的动态元素内存,这时便会对其他部分产生影响,c++11前未仔细优化的代码大都...

    C++的构造函数总结

    当一个对象创建的时候,编译器会调用这个对象的构造函数,在这个时候,或许大家会有疑问了:我并没有为对象指定构造函数,那么编译器调用的构造函数由哪里来呢?  有这点疑惑是一个好的开始,那么当我们没有指定...

    C++中拷贝构造函数的应用

    C++中拷贝构造函数的定义  有一个参数的类型是其类类型的构造函数是为拷贝构造函数。如下:  X::X( const X& x);  Y::Y( const Y& y, int =0 );  //可以是多参数形式,但其第二个即后继参数都有一个默认值 ...

    C++私有构造函数的作用

    通常我们都将构造函数的声明置于public区段,假如我们将其放入private区段中会发生什么样的后果?这意味着什么?  当我们在程序中声明一个对象时,编译器为调用构造函数(如果有的话),而这个调用将通常是外部的,...

    JavaScript构造函数原理及实现流程解析

    在学习构造函数之前我们需要知道我们学习构造函数需要学习什么: ...2.当我们需要调用构造函数时我们需要new <构造函数>,也就是产生一个实例化对象。 function Student(name,age,sex,height){ this.name=name;

    类的继承与派生实验

    1:掌握单继承和多继承下派生类的定义方法,理解基类成员在...3:理解同名冲突的产生原因,会使用虚基类来解决第三类同名冲突问题,并理解引入虚基类后构造函数、析构函数的调用顺序。 4:理解赋值兼容的相关使用方法。

    C++中拷贝构造函数的应用详解

    一、C++中拷贝构造函数的定义: 有一个参数的类型是其类类型的构造函数是为拷贝构造函数。 如下所示: X::X( const X& x); Y::Y( const Y& y, int =0 ); //可以是多参数形式,但其第二个即后继参数都有一个默认值 ...

    使用point类生成line类,使用组合和派生两种方法

    本设计题的目的是使学生掌握在不同的实现方法中,如何设计相应的构造函数和拷贝构造函数,进一步理解程序调用它们及析构函数的执行顺序,掌握组合类和派生类。另外本设计题目要让学生进一步掌握和理解类模板的技术...

    c++面向对象复习题答案版.doc

    5.用new申请某一个类的动态对象数组时,在该类中必须能够匹配到(该类的)构造函数,否则应用程序会产生一个编译错误。 6.静态数据成员必须在类外进行初始化,且静态数据成员的一个拷贝被类的所有对象( 共享 )。 7.在...

    新手学习C++入门资料

    上面例子中,第一次调用show()函数时,让编译器自动提供函数原型中指定的所有默认参数,第二次调用提供了第一个参数,而让编译器提供剩下的两个,第三次调用则提供了前面两个参数,编译器只需提供最后一个,最后一...

    C++编程思想习题

    14.8.1构造函数调用次序 14.8.2虚函数在构造函数中的行为 14.9析构函数和虚拟析构函数 14.10小结 14.11练习 第15章 模板和包容器类 15.1包容器和循环子 15.2模板综述 15.2.1C方法 15.2.2Smalltalk方法 15.2.3模板...

    零起点学通C++多媒体范例教学代码

    11.10.1 温习调用构造函数实现的类型转换 11.10.2 通过构造函数将变量转换为一个对象的成员变量 11.10.3 通过operator关键字进行转换 11.11什么可以重载,什么不可以重载 第12章 继承 12.1 什么是继承和派生 12.1.1...

    零起点学通C++学习_多媒体范例教学代码

    11.10.1 温习调用构造函数实现的类型转换 11.10.2 通过构造函数将变量转换为一个对象的成员变量 11.10.3 通过operator关键字进行转换 11.11什么可以重载,什么不可以重载 第12章 继承 12.1 什么是继承和派生 ...

    JavaScript 构造函数 面相对象学习必备知识

    代码如下: function A(x) { this.x = x; } var obj = new A(5);... 其实this代表的就是我们刚刚实例化出来的obj,就相当于我们使用obj去调用了构造函数A里面的属性、方法等等。 那么,我们怎么样去在构

    c.c++找工作面试重点结构图-mindmanager

    但仅仅用建立对象的最远派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基类子对象只初始化一次。 (7) 在一个成员初始化列表中同时出现...

    用C#编写复数

    编写一个完整的C#应用程序使用复数类Complex,并验证两个复数1+2i和3+4i相加产生一个新的复数4+6i。复数类Complex必须满足如下要求: (1)复数类Complex的属性有: RealPart: int型,代表复数的实数部分 ...

    浅谈JavaScript 中的this

    ​ 函数调用的时候会创建上下文,this 是组成上下文的一部分。因此每次函数被调用都会产生新的this,既this的值就是调用当前函数的对象。 2.作为普通函数在全局作用域中被使用 ​ 在全局作用域当中,this 永远指向 ...

Global site tag (gtag.js) - Google Analytics