看代码
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. 子类--构造器
分享到:
相关推荐
而且,只要它是最后的构造函数调用,那么在这个对象的生命期内,V PTR 将保持被初始化为指向这个 V TABLE。但如果接着还有一个更晚派生的构造函数被调用,这个构造函数又将设置 V PTR 指向它的 V TABLE,等。直到...
因此,在构造函数中调用虚方法可能会导致一些问题,因为虚方法可能会被子类重写,而在构造函数中调用虚方法可能会导致一些意外的结果。 例如,以下代码可能会导致警告“virtual member call in constructor”: ...
5. 程序中不能直接调用构造函数,在创建对象时系统自动调用构造函数。 6. 静态对象首次创建后不再重新产生。 缺省构造函数是指在定义类时没有定义构造函数的情况下,编译器自动产生的一个构造函数,该函数什么事也...
1. 构造函数的相互调用:在Java中,当为一个类创建了多个构造函数时,有时想在一个构造函数中调用另一个构造函数以减少代码量。这时可以使用this关键字来实现。 2. this关键字的作用:this关键字在Java中有多种用途...
同时,编译器可以在编译时检查构造函数调用的合理性,以减少潜在的错误。 3. **构造函数的可见性**: - 构造函数可以被声明为public、private或protected。 - **问题分析**:将构造函数声明为private可以防止外部...
在Demo1中,尽管`B`类覆盖了`strText`,但在`Main`方法中直接访问`B.strText`时,由于静态构造函数的执行顺序,实际上是调用了`A`类的静态构造函数,因此输出为"aaaa"。 在Demo2中,`B b = new B();`首先调用`B`的...
标题中的“dotnet C# 如果在构造函数抛出异常 是否可以拿到对象赋值的变量”是一个关于C#编程语言中的构造函数和异常处理的问题。在C#中,构造函数是用于初始化新创建的对象的特殊方法。当在构造函数中抛出异常时,...
"高质量C++编程指南 - 第9章 类的构造函数、析构函数与赋值函数" 本章主要介绍了C++类中的三个基本函数:...在示例 9-2(a) 中,类 B 的构造函数在其初始化表里调用了基类 A 的构造函数,以确保基类正确地被初始化。
3. **静态字段的访问**:如果在遍历过程中,你通过反射访问了某个类型的静态字段,即使没有显式调用静态构造函数,它也会在需要时被自动执行。 4. **潜在的陷阱**:需要注意的是,静态构造函数的执行顺序可能难以...
拷贝构造函数的参数通常是本类的一个引用,这样可以避免在拷贝过程中产生额外的对象副本。通过合理地定义拷贝构造函数,我们可以控制对象复制时的行为,例如深拷贝和浅拷贝,从而避免潜在的问题,如数据共享和资源...
在C++中,如果子类没有显式地调用父类的构造函数,编译器会自动调用父类的默认构造函数(如果没有提供默认构造函数,则编译器会产生错误)。因此,为了在子类中初始化父类的特定构造函数,必须显式地进行调用。 类...
在Java中,反射API(java.lang.reflect)允许我们获取类的信息,包括类名、构造函数、方法和字段,甚至可以在运行时创建和操作这些类的对象。这对于动态绑定、元编程和框架开发具有重要意义。 要调用一个类的静态...
C++中拷贝构造函数的定义 有一个参数的类型是其类类型的构造函数是为拷贝构造函数。如下: X::X( const X& x); Y::Y( const Y& y, int =0 ); //可以是多参数形式,但其第二个即后继参数都有一个默认值 ...
在上面的代码中,我们创建了两个名为 `line1` 和 `line2` 的对象,并将 `line1` 对象传递给 `line2` 对象,该操作会调用拷贝构造函数,并将 `line1` 对象的值复制到 `line2` 对象中。然后,我们将两个对象传递给 `...
2. **继承与构造函数调用**:如果类B继承自类A,并且类A有显示定义的构造函数,编译器会为类B生成一个默认构造函数,该构造函数在创建类B对象时调用基类A的构造函数,以确保基类的正确初始化。 3. **虚函数的存在**...
当你需要复制一个对象时,拷贝构造函数会被调用。默认的拷贝构造函数执行的是浅复制,即复制对象的引用,而不是引用的对象。对于包含指针或引用的数据成员,这可能导致两个对象共享同一块内存,可能产生意外的结果。...
在JavaScript中,当我们使用`new`关键字调用一个函数时,这个函数就充当了构造函数的角色。构造函数的第一个字母通常大写,以示区分。在示例中,`Person`就是一个构造函数,通过`this`关键字为新创建的对象设置属性...
4. **自动调用**:当创建类的对象时,相应的构造函数会自动调用,无需程序员显式调用。 **析构函数**与构造函数相对,用于清理对象在生命周期结束时产生的资源。其特点包括: 1. **特殊命名**:析构函数的名称是...