class A {
int super_var = 1;
}
class B extends A {
int sub_var = 2;
}
public class Demo{
public static void main(String []args){
A a = new B();
System.out.print(a.sub_var); //compile error
}
}
为什么这会以编译错误结束?引用(a)引用B的Object它有sub_var,为什么它受到限制?为什么参考(a)只能访问A?
中的字段答案 0 :(得分:5)
让我们说你有这些课程:
public class Animal() {
// ...
}
public class Fish extends Animal() {
public void swim() {...}
}
如果您宣布Animal
:
Animal x = new Fish();
您调用了swim()
方法
x.swim();
你期望它能起作用吗?我不这么认为,因为不是每个动物都能游泳。这就是为什么您必须明确指定动物x
是Fish
的原因:
((Fish) x).swim();
在您的情况下,如果您想调用该方法,则应指定(在技术上,它称为 cast )类型:
System.out.print(((B)a).sub_var);
注意:
修改强>
让我们看看这个例子:
Animal x;
if (some_condition)
x = new Fish();
else
x = new Cat();
x.swim();
存在这种限制,因为Java不知道在执行时分配给x的对象是否具有方法swim()
。所以为了避免这种情况,你必须转换为相应的类型来调用一个不存在于超类中的方法。
答案 1 :(得分:1)
起初听起来确实应该有效。 (在某些语言中它可能会这样做。)但想想这个例子:
public class Demo {
public static void main(String []args){
A a = new B();
print( a );
}
public static void print( A arg ) {
System.out.print(arg.sub_var); //compile error
}
}
这在功能上做同样的事情,但打印是另一种方法。如果您的版本有效,那么这个版本也可以使用。
但如果有人这样做呢?
Demo.print( new A() );
这应该会失败,因为A
没有sub_var
。它将不得不抛出某种运行时错误。
因此,Java中的设计决策不允许这样做,如果您将局部变量/ field / method参数声明为类型A
,那么您只能访问每个对象A
的内容。或者保证子类有。
如果您想要访问更多内容,则需要将其强制转换为子类,如果您在不适合的对象上尝试,将抛出异常。
A a = new A();
System.out.print(((B)a).sub_var); //ClassCastException is thrown here
答案 2 :(得分:0)
您无法通过父对象A的引用来访问B成员。
而是更改您的println
语句,如下所示,
System.out.print(((B)a).sub_var);
答案 3 :(得分:0)
父类中是否有一个名为sub_var的变量?不。这就是你得到错误的原因 -
sub_var cannot be resolved or is not a field
见这个
System.out.print(a.super_var); //okay
System.out.print(a.sub_var); //compile error
答案 4 :(得分:0)
创建B类型的对象并将其分配给A类型的变量。类型A不声明sub_var。此字段仅在类型B中声明。编译器仅查看在类型A中声明的内容,尽管该变量实例化为类型B的对象。
如果要访问sub_var,则必须将a转换为B.
System.out.println(((B)a).sub_var);
答案 5 :(得分:0)
sub_var
位于class B
,因此您只能通过class B
的引用进行访问。编译器A a = new B();
表示a
是class A
的实例。