Java在通用方法中限制了参数

Java bounded parameters in generic methods

我在通用方法中用有界参数测试了一些东西,发现了一些奇怪的行为。如果有人能解释下面代码片段中的两个错误,那就太好了。

假设有两类Class1Class2,都是从BaseClass扩展而来。Class2实现接口。

Class1中,我有一个方法,它按以下方式返回Class2的一个实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Class2 extends BaseClass implements Interface {

    @Override
    public void method() {
        System.out.println("test"); //$NON-NLS-1$
    }
}

public class Class1 extends BaseClass {

    public <T extends BaseClass & Interface> T getTwo() {
        return new Class2();
        // Error: Type mismatch: cannot convert from Class2 to T
    }

    public static void main(String[] args) {
        Interface two = new Class1().getTwo();
        // Error: Bound mismatch: The generic method getTwo() of type Class1 is
        // not applicable for the arguments (). The inferred type Interface is
        // not a valid substitute for the bounded parameter <T extends BaseClass
        // & Interface>
        System.out.println(two);
    }
}


第一个编译错误发生,因为方法声明的类型参数是由调用方指定的,而不是方法实现。也就是说,给定

1
class Class3 extends BaseClass implements Interface { ... }

呼叫者可以写

1
Class3 c3 = new Class1().<Class3>getTwo();

,但方法实现返回一个Class2,它不是T=Class3的子类型。

第二个编译错误发生,因为调用方未显式指定的类型参数是从方法参数和方法返回值分配给的变量类型推断出来的。这个推论在这里失败了。Java语言规范推荐的通常的解决方法是在这种情况下显式地指定类型参数(类型推断是为了简单的情况而方便;它不旨在覆盖所有的情况)。

至于如何正确地声明这个类型参数,我需要知道您试图用这些声明完成什么。


当你知道方法是Class2时,为什么要对方法getTwo使用泛型?只需执行以下操作:

1
2
3
public Class2 getTwo() {
    return new Class2();
}

如果您要重写方法public T getTwo(),当您的T的impl为Class2时,编译器将允许您声明您的impl为public Class2 getTwo()