我在理解下面的代码时遇到了问题(对行号进行了评论)
class Base {
void m1(Object o) {
}
void m2(String o) {
}
}
public class Overloading extends Base {
void m1(String s) {
}
void m2(Object o) {
}
public static void main(String[] args) {
Object o = new Object();
Base base1 = new Base();
base1.m1("");//**why this works perfect**
Base base = new Overloading();
base.m2(o);// **why compile time error** - The method m2(String) in the type Base is not applicable for the arguments (Object)
答案 0 :(得分:7)
编译器总是根据您调用它的引用的声明类型来解析方法调用。
调用方法时:
base1.m1("");
编译器在声明的base1
类型中查找方法签名,在这种情况下为Base
。 Base
中的匹配方法是:
void m1(Object o) { }
由于参数Object
可以接受String
参数,因此调用有效。您可以将子类对象传递给超类引用。
现在,第二次调用:
base.m2(o);
声明的base
类型再次为Base
。 Base
类中的匹配方法是:
void m2(String o) { }
由于您无法传递Object
引用,而String
被接受。编译器为您提供编译器错误。没有隐含的缩小转换。
您可以通过简单的任务更清楚地理解它:
Object ob = new Integer(3);
String str = ob; // This shouldn't be valid
Java不执行隐式缩小转换。从obj
到str
的分配不应该有效,否则您将在运行时获得ClassCastException
。
答案 1 :(得分:4)
在第base.m2(o)
行,编译器不知道base
是Overloading
- 它只知道它是Base
。为什么忘记了?因为你告诉它。
您告诉编译器将base
视为Base
,并将其声明为Base base = ...
。
因此,根据您的说明,编译器会将base
视为Base
,而不了解任何可能延伸或不延伸的Base
子类,以及它(正确)指出base
可能不支持任意m2
上的Object
。