Leo*_*zen 3 java inheritance overloading
关于在某些情况下调用哪个重载方法,我有一些问题.
情况1:
public void someMethod(Object obj){
    System.out.println("Object");
}
public void someMethod(InputStream is){
    System.out.println("InputStream");
}
public void someMethod(FilterInputStream fis){
    System.out.println("FilterInputStream");
}
我知道,如果我通过它String,它将打印"对象".但是,如果我传递一个InputStream怎么办?如果我传递一些像BufferedInputStream这样的东西会让人感到困惑.这会调用Object one,InputStream one还是FilterInputStream?方法的顺序是否重要?
案例2:
这有点棘手,因为它利用了多个接口继承.BlockingQueue和Deque都不是彼此的子/超类型,但两者都是BlockingDeque的超类型.Sun通过接口添加了多重继承,因为它们不需要树结构.BlockingDeque的声明是
public interface BlockingDeque extends BlockingQueue, Deque {.
public void someMethod(BlockingQueue bq){
    System.out.println("BlockingQueue");
}
public void someMethod(Deque bq){
    System.out.println("Deque");
}
public void someCaller(){
     BlockingDeque bd = new LinkedBlockingDeque();
     someMethod(bd);
}
这会调用someMethod(BlockingQueue)还是someMethod(Deque)?
案例3:
你可以把这两个结合起来:
public void someMethod(Queue q){
    //...
}
public void someMethod(Deque q){
    //...
}
public void someMethod(List p){
    //...
}
public void someCaller(){
    someMethod(new LinkedList());
}
同样的问题:someMethod(Queue),someMethod(Deque)或someMethod(List)?
案例4:
通过引入两个参数,你也可以使事情变得非常复杂:
public void someMethod(Collection c1, List c2){
    //...
}
public void someMethod(List c1, Collection c2){
    //...
}
public void someCaller(){
    someMethod(new ArrayList(), new ArrayList());
}
这会调用someMethod(Collection,List),反之亦然?
案例5:
当它们有不同的返回类型时会变得更糟:
public Class<?> someMethod(BlockingQueue bq){
    return BlockingQueue.class;
}
public String someMethod(Deque bq){
    return "Deque";
}
public void someCaller(){
     BlockingDeque bd = new LinkedBlockingDeque();
     System.out.println(someMethod(bd));
}
这些可能会非常糟糕.在这种情况下,someCaller会打印什么?someMethod(BlockingQueue).toString()或someMethod(Deque)?
一般来说,Java会调用最窄的非模糊定义,因此对于前几种情况,如果传递一个窄类型,它将调用最窄的函数,如果你传递一个更宽的类型(比如InputStream),你会获得更宽泛的类型的函数(在用于InputStream的case 1,即方法2).这是一个简单的测试,并注意向下转换会扩大类型,并调用更宽泛类型的方法.
核心问题是Java是否可以解析一个独特的调用函数.因此,这意味着如果您提供具有多个匹配项的定义,则需要匹配最高已知类型,或者唯一匹配更宽泛的类型,而不匹配更高类型.基本上:如果匹配多个函数,其中一个函数需要在层次结构中更高,以便Java解决差异,否则调用约定肯定是模糊的.
当方法签名不明确时,Java似乎会抛出编译错误.在我看来,案例4在规范上是最糟糕的例子,因此我编写了一个快速测试并确实得到了预期的编译错误,抱怨函数调用的模糊匹配.
案例5没有做任何更好或更糟的事情:Java不使用返回类型来消除调用哪个方法的歧义,因此它不会帮助你 - 而且由于定义已经含糊不清,你仍然会最终得到编译错误.
所以快速总结:
使用带有FilteredInputStream调用的普通InputStream调用时由于模糊调用导致的编译错误使用3rd def,调用实现InputStream但不是FilteredInputStream的东西使用2nd def,其他任何东西,1st def
第二次定义
模棱两可,会导致编译错误
模棱两可,会导致编译错误
模棱两可,会导致编译错误
最后,如果您怀疑自己正在调用您认为应该是的定义,那么您应该考虑更改代码以消除歧义,或者指定正确的类型参数来调用"正确"函数.Java会告诉你什么时候它不能做出明智的决定(当事情真的很模糊时),但避免任何这些问题的最好方法是通过一致和明确的实现.不要做奇怪的事情,如案例4,你不会遇到奇怪的问题.