如果我有这段代码:
interface Tre{
public void f();
}
public class TreA implements Tre{
int x = 1;
public void f(){
x++;
System.out.println("Y"+x);
}
public static void main(String[] a){
Tre a3 = new TreB(); a3.f();
}
}
class TreB extends TreA{
public void f(){
x--;
super.f();
System.out.println("X"+x);}
}
我不明白为什么输出是Y1 X1
。如果我扩展课程TreA
,我会覆盖其f()
方法并获取int x=1
的副本。致电super.f()
时应致电f()
所属的TreA
,但x
怎么办?我从未实例化过TreA
。为什么使用属于x
的{{1}}?在这种情况下,范围怎么样?
答案 0 :(得分:2)
扩展一个类意味着您的子类包含来自父类的所有内容。
我将覆盖它的f()方法并获取int x = 1
的副本
你没有得到副本,你只是拥有它(你继承了它)并且可以使用它。
使用x
的位置无关紧要,它始终是从TreA
继承的相同变量,因此当TreA.f()
修改它时,它正在修改{{1}的唯一实例你有。
我从未实例化过TreA
创建子类意味着您也在创建父类。在创建子类时,它的构造函数会自动调用。
您必须认为x
本身包含 TreB
,然后您可以添加内容并进行覆盖。
为了更好地可视化情况,这是你的A类:
这是它的子类B:
你可以看到B 中的TreA
变量是来自A类的变量,而不是副本。
答案 1 :(得分:0)
当您实例化TreB时,会构建TreA(更具体地说,这是TreB)。 TreB没有字段x将字段隐藏在TreA中,因此该对象只有一个字段x,在TreA中定义。您可以从TreB访问它,因为您没有将其声明为私有。
这是不好的做法btw,非final字段应该始终是私有的,以避免这样的问题。使用getter从TreA获取值以用于TreB。
答案 2 :(得分:0)
每当你从任何地方调用该类时,变量都会自动实例化。 调用默认构造函数并设置变量值。
您可以看到此示例。调用该类时设置变量值。
public class TreA {
int x = 1;
public static void main(String[] a){
TreA b = new TreA();
System.out.println(b.x);
}
}
输出为1