我发现了类似的问题,但我不确定答案是否正确。我的java考试有这个问题。
哪个构造函数初始化变量x3?
class X {
int x1, x2, x3;
}
class Y extends X {
int y1;
Y() {
x1 = 1;
x2 = 2;
y1 = 10;
}
}
class Z extends Y {
int z1;
Z() {
x1 = 3;
y1 = 20;
z1 = 100;
}
}
public class Test3 {
public static void main(String[] args) {
Z obj = new Z();
System.out.println(obj.x3 + ", " + obj.y1 + ", " +obj.z1);
}
}
数目:
感谢您的帮助。
答案 0 :(得分:4)
子类继承其超类的所有字段。因此,当子类的构造函数初始化类属性时,必须初始化继承的超类属性。为了确保这一点,子类的构造函数首先调用超类的构造函数,然后继续使用自己的构造函数。
在您的情况下,Z
扩展Y
而Y
扩展X
,因此当您编写new Z()
时,它会调用构造函数Z()
,隐含地调用调用Y()
的{{1}}。现在构造函数X()
在哪里?在java中,当一个类没有构造函数时,编译器会向其添加一个默认的无参数构造函数。因此,您的班级X()
已经有一个构造函数X
。此构造函数会将X()
,x1
和x2
初始化为其默认值x3
。
情况是,在0
,您正在呼叫main
,Z()
正在呼叫Z()
而Y()
正在呼叫Y()
。最终,构造函数X()
初始化X()
。
答案 1 :(得分:2)
总结一下我在一些评论中所写的内容:
我认为答案'D'是正确的,即使它听起来很直观。 在显示的代码中,永远不会为x3分配值。因此它具有默认值。在“X”的构造函数运行之前设置此默认值。因此,默认值必须由特殊的东西分配。我希望Object类的构造函数能够做到这一点。它执行VM内部所需的一些操作。
要在构造函数运行之前验证字段是否有值,请使用测试用例:
class A {
A() { printMember(); }
void printMember() {}
}
class B extends A {
private int x;
@Override
void printMember() { System.out.println(x); }
}
public class TestAssignment {
@org.junit.Test
public void createInstance() { new B(); }
}
而不是获取未初始化的值错误,它打印'0' - 如果您覆盖B的构造函数中的值,它仍将打印'0'。这证明了在A或B的构造函数运行之前赋值。因此,问题的答案A.,B。和C.必须是错误的,只有D.遗骸。
答案 2 :(得分:2)
这里当你创建Z类的对象时,它将首先初始化X类的默认构造函数,因为X是Z的祖父类,然后初始化Y类的无参数构造函数,因为Y是父类的X然后初始化Z类的无参数构造函数。
初始化X的默认构造函数时,它将指定x1 = 0,x2 = 0和x3 = 0,因为它们都是类X的实例变量。
初始化Y类的无参数构造函数时,它将赋值x1 = 1, x2 = 2,y1 = 10.
初始化Z类的无参数构造函数时,它将赋值x1 = 3, y1 = 20,z1 = 100。
所以这里的答案将是选项A,即只有X类的默认构造函数。