为什么在使用超类引用调用子类方法时会出现编译时错误?
我知道在方法覆盖的情况下会发生多态。 但我对下面的内容感到有些困惑。
class A { public void hi() { System.out.println("A "+this.getClass().getName()); } } class B extends A { public void bye() { System.out.println("B "+this.getClass().getName()); } } class Ideone { public static void main (String[] args) throws java.lang.Exception { A a = new B(); a.hi(); a.bye(); } }
输出:
Main.java:35: error: cannot find symbol a.bye(); ^ symbol: method bye() location: variable a of type A 1 error
为什么这会产生编译时错误?
在a = new B()
, B
类对象是在运行时创建的,因此a
一个指向B
类对象的引用变量。
现在,如果我们调用B
的类方法bye()
,为什么它是编译器时间错误?
a
变量可以在运行时包含A
类的实例或A
任何子类。 因此,您只能为该变量调用A
类A
方法。
编译器在确定哪些方法调用有效时,只关心变量的编译时类型。
变量a
的声明类型是A.编译器不知道(也不应该知道)它在运行时的具体类型是什么B.它只知道它是A,并且没有bye()
方法在一个。
整个做点
A a = new B();
并不是
B a = new B();
是清楚地说a是A,并且可以有任何具体类型,只要conrete类型扩展A.如果你以后找到更好的A实现,你必须能够将该行更改为
A =新的BetterImplementation();
并编译代码。
将新的B
实例分配给类型A
的引用就像让它佩戴唯一看到方法定义的A眼镜。 那就是你得到A
所描述的界面。 即使该实例具有bye
的实现,您也只能访问hi
。
理解这一点的一个简单方法是A a实际上可能指向B的对象,但在编译期间编译器不知道这一点。
编译器只检查引用即’a’并查看它的类,即’A’是否具有其引用’a’试图调用的方法。
在您的情况下,引用’a’没有一个名为bye()的方法,因此根据编译器不能进行这样的调用,这就是您看到该错误的原因。
我想你已经从其他答案得到了你的多态性问题的答案。 除此之外,您还可以使用类型转换以这种方式使代码工作。
(B)a.bye();
这是一个很好的解释,您可以阅读有关引用与对象类型的内容。 这是关于铸造的好文章。
您只能从父类类型访问父类方法。
A a = new B();
解决方案1:
将父级更改为子级( B b = new B ()
)并调用B方法。
解决方案2:
检查parent是否是Child对象的实例。 如果是,则将父项转换为Child并调用该方法。
class Ideone { public static void main (String[] args) throws java.lang.Exception { A a = new B(); a.hi(); if ( a instanceof B){ ((B)a).bye(); } } }
输出:
AB BB
看一下instanceof上的oracle文档页面
instanceof运算符将对象与指定的类型进行比较。 您可以使用它来测试对象是否是类的实例,子类的实例或实现特定接口的类的实例。
多态性基本上是一个对象采取多种forms的能力。 由于您的父类是指子类对象,因此它是多态的。
Main.java:35: error: cannot find symbol a.bye(); ^ symbol: method bye() location: variable a of type A 1 error
您收到此错误是因为您尝试从超类引用调用子类的方法。
在这里,您将subClass对象ref分配给超类,这很好。 但是超类只能调用它自己已知的方法和数据。
A a = new B(); a.hi(); // member of super class a.bye(); // Not a member a super class
- HttpSessionListener(sessionCreated / destroyed) – 奇怪的行为
- hibernate。 ClassicQueryTranslatorFactory与ASTQueryTranslatorFactory
- 我使用了同步列表,我仍然得到ConcurrentModificationException
- 如何使用Hibernate Criteria懒惰地获取字段
- 如何使用指定的Charset将文本附加到Java 8中的文件
- java堆内存管理内存不足
- 我如何在名称,数字,金钱,日期等内容中对文字进行分类?
- prunsrv.exe服务无法启动
- 如何在java中的http post中发送json对象