【发布时间】:2015-03-16 18:45:53
【问题描述】:
我有一个关于泛型的问题。假设我有 3 个类“Foo”、“Bar”(它是 Foo 的子类)、一个类“Factory”和一个接口“TestInterface”。 我想写一个泛型方法,它只允许“直接”实现接口的对象,所以没有子类。 这对我来说很难,因为 Java8 似乎比 Java7 更“聪明”。
举个例子:
public interface TestInterface<T extends TestInterface<T>> {
}
public class Foo implements TestInterface<Foo>{
}
public class Bar extends Foo {
}
public class Factory {
public static <T extends TestInterface<T>> T doSth(T arg) {
return arg;
}
}
好的,这些是我的课程。现在在doSth(T arg) 方法中,我想在这种情况下允许 Foo 对象,因为它是唯一“直接”实现接口的类。
显然这样的东西现在不会编译:
Bar b = Factory.doSth(new Bar());
因为 Bar 没有实现 TestInterface<Bar>。
好吧,我现在的问题是,这一行将毫无问题地编译:
Foo f = Factory.doSth(new Bar());
即使泛型参数是 T 并且 T 应该用它自己的类来实现接口(对不起,真的不知道怎么说,希望你明白我的意思),编译器接受“Bar”作为参数。
所以编译器必须表现得像“好吧 Bar 不适合,但也许超类适合”。然后它“看到”它与 superlcas“Foo”一起工作。 然后 Bar 将被视为 Foo,因为每个 Bar 都是某种 Foo 或类似的东西?至少我是这么想的。
好吧,如果我尝试用 Java7 编译该行,它会失败。所以看起来Java8在类型擦除方面更聪明一点?!
在 Java8 中有什么方法不允许子类,这样就不会编译?:
Foo f = Factory.doSth(new Bar());
希望你能理解我的问题,我很少用英文写作。
问候
【问题讨论】:
-
如果你想让
Foo f = Factory.doSth(new Bar());不编译,那么Bar一定不能实现TestInterface,这意味着它不能扩展Foo.. -
如果
Bar是Foo的子类,那么Bar的实例是Foo的实例,并且Bar的实例必须在任何时候被接受Foo被接受。为什么不希望Bar在这里被接受? -
@FelRPI 不同之处在于类型推断在两个版本中的工作方式,在 Java 8 中发生了变化。事实上,Java 8 中的类型推断有所改进。
-
在我的机器上,使用 Java 1.8.0_40,你的行没有编译。你确定你的例子吗?您使用的是哪个 Java 版本?
-
@FelRPI
Foo f = Factory.<Foo>doSth(new Bar());在 Java 7 中应该可以工作(明确指定类型参数)。
标签: java generics subclass type-inference