简体   繁体   English

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

[英]Java - generic classes hierarchy and generic methods overloading

I have a (non abstract) generic base class A<L,M> , an abstract generic sub class B<K, L, M> extends A<L,M> and a (non abstract) class C extends B<Integer, Integer, Void> : 我有一个(非抽象的)通用基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> { }

I have a utils class that has a few methods, two are relevant here: 我有一个具有几个方法的utils类,这里有两个相关的方法:

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

To be clear, both methods have the same name. 需要明确的是,这两种方法具有相同的名称。
If I call doSomething(c); 如果我打电话给doSomething(c); (where C c ) it goes as expected to the 1st method. (其中C c )按预期方法进行。
My issue is with the following code (at another class that uses the utils): 我的问题是以下代码(在使用utils的另一个类中):

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

So here a is actually C but it goes to the second method, I am not sure if I made a mistake in the code or this is actually the expected behavior. 因此,这里的a实际上是C但是它转到第二种方法,我不确定是否在代码中犯了错误,或者这实际上是预期的行为。

or this is actually the expected behavior. 或这实际上是预期的行为。

Yes, it's the expected behavior. 是的,这是预期的行为。

The compiler chooses which method is run, and it doesn't know that it is a B (because you've said it's an A ). 编译器选择运行哪个方法,并且它不知道它是B (因为您说过它是A )。 So it doesn't know if the first overload is safe to invoke, but it knows the second overload is. 因此,它不知道第一个重载是否可以安全调用,但是它知道第二个重载是安全的。

This is the expected behavior. 这是预期的行为。 The runtime type of a is inconsequential, as this method resolution is done in compile time. 的运行时类型a是无关紧要的,因为这种方法解决在编译时完成的。 Since doSomething(B) cannot be applied to an argument of type A , the method is resolved to doSomething(A) . 由于doSomething(B)无法应用于类型A的参数,因此该方法解析为doSomething(A)

You could handle this yourself by explicitly downcasting a : 您可以通过显式下调a自己处理:

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

... but, well, in a word - yuck. ...但是,总之--。

The more idiomatic way to address this would be to have doSomething as a method of A and override ( not overload ) it in B . 解决这个问题的更惯用的方法是将doSomething作为A的方法,并在B 覆盖而不是重载 )它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM