`
DoubleEO
  • 浏览: 157830 次
  • 性别: 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  
构造函数不能调用可被子类复写的方法,构造函数不能创建新线程
前者有可能导致程序初始化不完整,后者可能导致互相等待初始化而死锁

相关推荐

    构造函数不能为虚函数的理由

    而且,只要它是最后的构造函数调用,那么在这个对象的生命期内,V PTR 将保持被初始化为指向这个 V TABLE。但如果接着还有一个更晚派生的构造函数被调用,这个构造函数又将设置 V PTR 指向它的 V TABLE,等。直到...

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

    因此,在构造函数中调用虚方法可能会导致一些问题,因为虚方法可能会被子类重写,而在构造函数中调用虚方法可能会导致一些意外的结果。 例如,以下代码可能会导致警告“virtual member call in constructor”: ...

    构造函数和析构函数PPT课件.pptx

    5. 程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数。 6. 静态对象首次创建后不再重新产生。 缺省构造函数是指在定义类时没有定义构造函数的情况下,编译器自动产生的一个构造函数,该函数什么事也...

    Java构造函数的相互调用代码示例

    1. 构造函数的相互调用:在Java中,当为一个类创建了多个构造函数时,有时想在一个构造函数中调用另一个构造函数以减少代码量。这时可以使用this关键字来实现。 2. this关键字的作用:this关键字在Java中有多种用途...

    论C++构造函数中的不合理设计

    同时,编译器可以在编译时检查构造函数调用的合理性,以减少潜在的错误。 3. **构造函数的可见性**: - 构造函数可以被声明为public、private或protected。 - **问题分析**:将构造函数声明为private可以防止外部...

    C#中静态构造函数的几点说明介绍

    在Demo1中,尽管`B`类覆盖了`strText`,但在`Main`方法中直接访问`B.strText`时,由于静态构造函数的执行顺序,实际上是调用了`A`类的静态构造函数,因此输出为"aaaa"。 在Demo2中,`B b = new B();`首先调用`B`的...

    dotnet C# 如果在构造函数抛出异常 是否可以拿到对象赋值的变量.rar

    标题中的“dotnet C# 如果在构造函数抛出异常 是否可以拿到对象赋值的变量”是一个关于C#编程语言中的构造函数和异常处理的问题。在C#中,构造函数是用于初始化新创建的对象的特殊方法。当在构造函数中抛出异常时,...

    高质量C++C编程指南 - 第9章 类的构造函数、析构函数与赋值函数.pdf

    "高质量C++编程指南 - 第9章 类的构造函数、析构函数与赋值函数" 本章主要介绍了C++类中的三个基本函数:...在示例 9-2(a) 中,类 B 的构造函数在其初始化表里调用了基类 A 的构造函数,以确保基类正确地被初始化。

    dotnet C# 反射扫描程序集所有类型会不会触发类型静态构造函数.rar

    3. **静态字段的访问**:如果在遍历过程中,你通过反射访问了某个类型的静态字段,即使没有显式调用静态构造函数,它也会在需要时被自动执行。 4. **潜在的陷阱**:需要注意的是,静态构造函数的执行顺序可能难以...

    堆与拷贝构造函数PPT课件.pptx

    拷贝构造函数的参数通常是本类的一个引用,这样可以避免在拷贝过程中产生额外的对象副本。通过合理地定义拷贝构造函数,我们可以控制对象复制时的行为,例如深拷贝和浅拷贝,从而避免潜在的问题,如数据共享和资源...

    C++类继承之子类调用父类的构造函数的实例详解

    在C++中,如果子类没有显式地调用父类的构造函数,编译器会自动调用父类的默认构造函数(如果没有提供默认构造函数,则编译器会产生错误)。因此,为了在子类中初始化父类的特定构造函数,必须显式地进行调用。 类...

    通过反射调用静态方法

    在Java中,反射API(java.lang.reflect)允许我们获取类的信息,包括类名、构造函数、方法和字段,甚至可以在运行时创建和操作这些类的对象。这对于动态绑定、元编程和框架开发具有重要意义。 要调用一个类的静态...

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

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

    详解C++ 拷贝构造函数

    在上面的代码中,我们创建了两个名为 `line1` 和 `line2` 的对象,并将 `line1` 对象传递给 `line2` 对象,该操作会调用拷贝构造函数,并将 `line1` 对象的值复制到 `line2` 对象中。然后,我们将两个对象传递给 `...

    对C++默认构造函数的一点重要说明

    2. **继承与构造函数调用**:如果类B继承自类A,并且类A有显示定义的构造函数,编译器会为类B生成一个默认构造函数,该构造函数在创建类B对象时调用基类A的构造函数,以确保基类的正确初始化。 3. **虚函数的存在**...

    中国科学院C#课件、堆与拷贝构造函数

    当你需要复制一个对象时,拷贝构造函数会被调用。默认的拷贝构造函数执行的是浅复制,即复制对象的引用,而不是引用的对象。对于包含指针或引用的数据成员,这可能导致两个对象共享同一块内存,可能产生意外的结果。...

    详解js产生对象的3种基本方式(工厂模式,构造函数模式,原型模式).docx

    在JavaScript中,当我们使用`new`关键字调用一个函数时,这个函数就充当了构造函数的角色。构造函数的第一个字母通常大写,以示区分。在示例中,`Person`就是一个构造函数,通过`this`关键字为新创建的对象设置属性...

    C++构造函数和析构函数的使用与讲解

    4. **自动调用**:当创建类的对象时,相应的构造函数会自动调用,无需程序员显式调用。 **析构函数**与构造函数相对,用于清理对象在生命周期结束时产生的资源。其特点包括: 1. **特殊命名**:析构函数的名称是...

Global site tag (gtag.js) - Google Analytics