Java-通用类层次结构和通用方法重载

时间:2018-11-05 21:52:52

标签: java generics inheritance overloading

我有一个(非抽象的)通用基数class A<L,M>,一个抽象的通用子类class B<K, L, M> extends A<L,M>和一个(非抽象的)class C extends B<Integer, Integer, Void>

public class A<L,M> { }

public abstract class B<K, L, M> extends A<L,M> { }

public class C extends B<Integer, Integer, Void> { }

我有一个utils类,其中有一些方法,这里有两个相关的方法:

public static <K, L, M> void doSomething(B<K, L, M> b) {...}
public static <L, M>    void doSomething(A<L, M>    a) {...}

要清楚,这两种方法的名称相同。
如果我调用doSomething(c);(在C c处),则按预期方法进行第一种方法。
我的问题是以下代码(在使用utils的另一个类中):

private void doSomethingMoreComplex(A a) { // a is actually C
    Utils.doSomething(a);
}

因此,这里的a实际上是C,但是它涉及第二种方法,我不确定是否在代码中犯了错误,或者这实际上是预期的行为。

2 个答案:

答案 0 :(得分:3)

  

或者这实际上是预期的行为。

是的,这是预期的行为。

编译器选择运行哪个方法,并且它不知道它是B(因为您已经说过它是A)。因此,它不知道第一个重载是否可以安全调用,但它知道第二个重载是安全的。

答案 1 :(得分:3)

这是预期的行为。 a的运行时类型无关紧要,因为此方法解析是在编译时完成的。由于doSomething(B)无法应用于类型为A的参数,因此该方法将解析为doSomething(A)

您可以通过显式下传a来自己处理:

private void doSomethingMoreComplex(A a) { // a is actually C
    if (a instanceof B) {
        Utils.doSomething((B) a);
    } else {
        Utils.doSomething(a);
    }
}

...但是,总而言之-。

解决此问题的更惯用的方法是将doSomething作为A的一种方法,并对其进行覆盖不超载B