我添加了三个带参数的方法:
public static void doSomething(Object obj) {
System.out.println("Object called");
}
public static void doSomething(char[] obj) {
System.out.println("Array called");
}
public static void doSomething(Integer obj) {
System.out.println("Integer called");
}
当我调用doSomething(null)
时,编译器会将错误视为模糊方法。问题是因为Integer
和char[]
方法还是Integer
和Object
方法?
答案 0 :(得分:198)
Java将始终尝试使用可用方法的最具体适用版本(请参阅JLS §15.12.2)。
Object
,char[]
和Integer
都可以将null
作为有效值。因此,所有3个版本都适用,因此Java必须找到最具体的版本。
由于Object
是char[]
的超类型,因此数组版本比Object
版本更具体。因此,如果只存在这两种方法,则会选择char[]
版本。
当char[]
和Integer
版本都可用时,两者都比Object
更具体,但没有一个比另一个更具体,所以Java无法决定调用哪一个。在这种情况下,您必须通过将参数强制转换为适当的类型来明确提及要调用的那个。
请注意,在实践中,这个问题比人们想象的要少得多。这样做的原因是,只有在您使用null
或使用非特定类型的变量(例如Object
)显式调用方法时才会发生这种情况。
相反,以下调用将是完全明确的:
char[] x = null;
doSomething(x);
虽然您仍在传递值null
,但Java确切地知道要调用哪个方法,因为它会考虑变量的类型。
答案 1 :(得分:39)
当使用null
参数调用时,这三种方法中的每一对都是不明确的。因为每个参数类型都是引用类型。
以下是用null调用你的一个特定方法的三种方法。
doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);
如果您真的计划使用null
参数调用这些方法,我建议您删除这种歧义。这样的设计将来会产生错误。
答案 2 :(得分:4)
null
是三种类型中的任何一种的有效值;所以编译器无法决定使用哪个函数。请改用doSomething((Object)null)
或doSomething((Integer)null)
之类的内容。
答案 3 :(得分:2)
Java中的每个类都扩展了Object类.Even Integer类也扩展了Object。因此,Object和Integer都被视为Object实例。因此,当您将null作为参数传递时,编译器会混淆要调用哪个对象方法,即使用参数Object或参数Integer,因为它们都是对象,并且它们的引用可以为null。但是java中的原语并没有扩展Object。
答案 4 :(得分:1)
我试过这个,当只有一对重载方法并且其中一个具有参数类型Object时,编译器将始终选择具有更具体类型的方法。但是当存在多个特定类型时,编译器会抛出一个模糊的方法错误。
由于这是一个编译时事件,因此只有在故意将null传递给此方法时才会发生这种情况。如果这是故意完成的,那么最好在没有参数的情况下再次重载此方法或者完全创建另一个方法。
答案 5 :(得分:0)
因为doSomething(char [] obj)和doSomething(Integer obj)而存在歧义。
char []和Integer对于null来说都是相同的,这就是为什么它们不明确的原因。
答案 6 :(得分:0)
class Sample{
public static void main (String[] args) {
Sample s = new Sample();
s.printVal(null);
}
public static void printVal(Object i){
System.out.println("obj called "+i);
}
public static void printVal(Integer i){
System.out.println("Int called "+i);
}
}
输出为Int,称为null,因此模糊度与char []和Integer