Fel*_*RPI 5 java generics type-inference subclass
我有一个关于泛型的问题。所以假设我有 3 个类“Foo”、“Bar”(它是 Foo 的子类)、一个类“Factory”和一个接口“TestInterface”。我想编写一个通用方法,它只允许“直接”实现接口的对象,所以没有子类。这对我来说很难,因为 Java8 似乎比 Java7“更聪明”。
所以这里有一个例子:
public interface TestInterface<T extends TestInterface<T>> {
}
Run Code Online (Sandbox Code Playgroud)
public class Foo implements TestInterface<Foo>{
}
Run Code Online (Sandbox Code Playgroud)
public class Bar extends Foo {
}
Run Code Online (Sandbox Code Playgroud)
public class Factory {
public static <T extends TestInterface<T>> T doSth(T arg) {
return arg;
}
}
Run Code Online (Sandbox Code Playgroud)
好的,这些是我的课。现在在doSth(T arg)方法中,我想在这种情况下允许 Foo 对象,因为它是唯一“直接”实现接口的类。
显然这样的东西现在不会编译:
Bar b = Factory.doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
因为 Bar 没有实现TestInterface<Bar>.
好的,我现在的问题是,这一行将编译没有任何问题:
Foo f = Factory.doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
即使泛型参数是 T 并且 T 应该用它自己的类实现接口(抱歉,真的不知道怎么说,希望你知道我的意思),编译器接受“Bar”作为参数。
所以编译器必须表现得像“好吧,Bar 不适合,但也许超类适合。” 然后它“看到”它与超级类“Foo”一起工作。然后 Bar 将被视为 Foo,因为每个 Bar 都是某种 Foo 或类似的东西?至少我是这么想象的。
好吧,如果我尝试使用 Java7 编译该行,则会失败。所以看起来Java8在类型擦除方面更聪明一点?!
Java8 中是否有任何方法不允许子类,从而无法编译?:
Foo f = Factory.doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
希望你理解我的问题,我很少用英语写作。
问候
之所以Foo f = Factory.doSth(new Bar());在 Java 8 而不是 Java 7 中有效,是因为 Java 8 具有更好的类型推断。在 Java 7 中,类型被推断为:
Foo f = Factory.<Bar>doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
Bar不实现TestInterface<Bar>,但它确实TestInterface<Foo>通过继承实现。Java 8 的类型推断得到了提升,类型将被推断为:
Foo f = Factory.<Foo>doSth(new Bar());
Run Code Online (Sandbox Code Playgroud)
请注意,Factory.<Foo>doSth()需要一个Foo作为参数,因此new Bar()被隐式转换为Foo可以正常工作的形式。
恐怕没有办法解决这个问题。您始终能够将对象向上转换为其超类。您可以创建Foo final,但这Foo完全不允许子类化。
| 归档时间: |
|
| 查看次数: |
1374 次 |
| 最近记录: |