abstract class Type<K extends Number> {
abstract <K> void use1(Type<K> k); // Compiler error (Type parameter K is not within its bounds)
abstract <K> void use2(Type<? extends K> k); // fine
abstract <K> void use3(Type<? super K> k); // fine
}
方法泛型类型K隐藏类泛型类型K,因此<K>
与<K extends Number>
中的use1()
不匹配。编译器对新的泛型类型{<K>
不知道任何有用的内容{在use2()
和use3()
中{1}},但编译仍然合法。为什么<? extends K>
(或<? super K>
)匹配<K extends Number>
?
答案 0 :(得分:9)
您遇到的问题是有两种K
类型。如果重命名,可能会更清楚。
abstract class Type<N extends Number> {
abstract <K extends Number> void use1(Type<K> k); // fine
abstract <K> void use2(Type<? extends K> k); // fine
abstract <K> void use3(Type<? super K> k); // fine
}
在某些情况下,您必须提供编译器可以推断的重复信息,以及其他您不能提供的信息。在Java 7中,它添加了一个<>
菱形符号,告诉编译器推断它以前没有的类型。
说明我的意思。以下是创建泛型类实例的不同方法。有些要求给出两次类型,其他只需要一次。编译器可以推断出类型。
通常,Java在大多数其他语言中都不会推断类型。
class Type<N extends Number> {
private final Class<N> nClass;
Type(Class<N> nClass) {
this.nClass = nClass;
}
static <N extends Number> Type<N> create(Class<N> nClass) {
return new Type<N>(nClass);
}
static void main(String... args) {
// N type is required.
Type<Integer> t1 = new Type<Integer>(Integer.class);
// N type inferred in Java 7.
Type<Integer> t2 = new Type<>(Integer.class);
// type is optional
Type<Integer> t3 = Type.<Integer>create(Integer.class);
// type is inferred
Type<Integer> t4 = create(Integer.class);
}
答案 1 :(得分:5)
当你定义这样的方法时:
abstract <K> void use1(Type<K> k);
您实际上在类定义中隐藏了类型K
。您应该能够定义如下方法:
abstract void use1(Type<K> k);
答案 2 :(得分:4)
首先,让我们重写它以避免阴影:
abstract class Type<N extends Number> {
abstract <K> void use1(Type<K> k);
abstract <K> void use2(Type<? extends K> k);
abstract <K> void use3(Type<? super K> k);
}
在第一种方法中,K
充当Type<N extends Number>
的类型参数,因此其值应符合Type
的{{1}}的范围。但是,方法声明对N
的值没有任何限制,因此它不合法。如果您在K
上添加必要的限制,那将是合法的:
K
在以下方法中,abstract <K extends Number> void use1(Type<K> k);
的实际类型参数未知(Type
),?
对其施加了额外的限制,因此这些声明中没有任何违法行为。
这是一个更实际的例子,具有类似的声明:
K
答案 3 :(得分:0)
这是一个灰色区域; javac 7和6不同意; JLS3已经过时了;不知道新规格在哪里。