Java error: CAP#1, int where CAP#1 is a fresh type-variable: CAP#1 extends Object from capture of?
Java error: CAP#1, int where CAP#1 is a fresh type-variable: CAP#1 extends Object from capture of?
有了这个通用元组 class
public class Pair< T1, T2 > {
private final T1 first;
private final T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public T1 getFirst() {
return first;
}
public T2 getSecond() {
return second;
}
}
和这个driver
public class PairDriver {
public static void main(String[] args) {
Pair<?, ?>[] s = new Pair<?, ?>[3];
s[0] = new Pair<String, Integer>("a", 1);
s[1] = new Pair<String, Integer>("b", 2);
s[2] = new Pair<String, Integer>("c", 3);
System.out.println( s[0].getFirst().getClass().getName() ); // Should be String
System.out.println( s[0].getSecond().getClass().getName() ); // Should be Integer
System.out.println( s[0].getFirst() );
System.out.println( s[0].getFirst() + "!!!" ); // Operation works
System.out.println( s[0].getSecond() );
System.out.println( s[0].getSecond() + 2 ); // Operation FAILS...
}
}
我收到以下错误:
pairDriver.java:17: error: bad operand types for binary operator '+'
System.out.println( s[0].getSecond() + 2 ); // Operation FAILS...
^
first type: CAP#1
second type: int
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
error: compilation failed
我很困惑为什么会这样。直到标记为 // Operation FAILS...
运行 的那一行之前的所有行——类型似乎是正确的,操作甚至可以与 String 一起使用,但不能与 Integer 一起使用。
作为 follow-up:我看到有人通过用类型替换通配符 ?
来修复类似的错误。我不明白为什么这在他们的情况下有效,但在这里不适用,因为用 Pair<String, Integer>[] s = new Pair<String, Integer>[3];
之类的类型声明数组会导致不同的错误:
pairDriver.java:5: error: generic array creation
Pair<String, Integer>[] s = new Pair<String, Integer>[3];
^
1 error
error: compilation failed
我对为什么会发生这种情况感到困惑和好奇。
I'm confused as to why this happens
就编译器而言,您正在向 int 添加一些对象。
它没有更多信息,因为该对中第二个元素的类型是 ?
(如 Pair<?, ?>
)。它不知道该值实际上是一个 Integer。
As a follow-up
由于类型擦除,您无法使用不可具体化的元素类型创建数组。
可具体化的类型是一种在运行时关于该类型的一切都已知的类型。非泛型是可具体化的;所有类型参数都是通配符的泛型类型是可具体化的;其他泛型类型不是。
泛型和数组是不愉快的伙伴。如果您使用泛型,请改用 List
。
List<Pair<String, Integer>> s = new ArrayList<>();
s.add(new Pair<String, Integer>("a", 1));
s.add(new Pair<String, Integer>("b", 2));
s.add(new Pair<String, Integer>("c", 3));
添加到您的 Pair class 中的数据类型在运行时被删除。编译器只知道来自 getFirst()
和 getSecond()
的数据是 扩展 Object
的东西 ,但它不知道那是什么某事是具体的。
由于 Object
有一个 .toString()
方法,当您使用字符串连接运算符时会隐式调用该方法,因此 s[0].getFirst() + "!!!"
工作得很好。但是 <? extends Object>
(这是编译器在您使用它时所知道的关于您的类型的所有信息)作为加法运算符的左侧无效。
您可以通过将结果转换为整数来解决这个问题,如下所示:
System.out.println( (Integer) s[0].getSecond() + 2 );
但请注意,这只是您告诉编译器 "trust me, this is definitely an Integer"。
有了这个通用元组 class
public class Pair< T1, T2 > {
private final T1 first;
private final T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public T1 getFirst() {
return first;
}
public T2 getSecond() {
return second;
}
}
和这个driver
public class PairDriver {
public static void main(String[] args) {
Pair<?, ?>[] s = new Pair<?, ?>[3];
s[0] = new Pair<String, Integer>("a", 1);
s[1] = new Pair<String, Integer>("b", 2);
s[2] = new Pair<String, Integer>("c", 3);
System.out.println( s[0].getFirst().getClass().getName() ); // Should be String
System.out.println( s[0].getSecond().getClass().getName() ); // Should be Integer
System.out.println( s[0].getFirst() );
System.out.println( s[0].getFirst() + "!!!" ); // Operation works
System.out.println( s[0].getSecond() );
System.out.println( s[0].getSecond() + 2 ); // Operation FAILS...
}
}
我收到以下错误:
pairDriver.java:17: error: bad operand types for binary operator '+'
System.out.println( s[0].getSecond() + 2 ); // Operation FAILS...
^
first type: CAP#1
second type: int
where CAP#1 is a fresh type-variable:
CAP#1 extends Object from capture of ?
1 error
error: compilation failed
我很困惑为什么会这样。直到标记为 // Operation FAILS...
运行 的那一行之前的所有行——类型似乎是正确的,操作甚至可以与 String 一起使用,但不能与 Integer 一起使用。
作为 follow-up:我看到有人通过用类型替换通配符 ?
来修复类似的错误。我不明白为什么这在他们的情况下有效,但在这里不适用,因为用 Pair<String, Integer>[] s = new Pair<String, Integer>[3];
之类的类型声明数组会导致不同的错误:
pairDriver.java:5: error: generic array creation
Pair<String, Integer>[] s = new Pair<String, Integer>[3];
^
1 error
error: compilation failed
我对为什么会发生这种情况感到困惑和好奇。
I'm confused as to why this happens
就编译器而言,您正在向 int 添加一些对象。
它没有更多信息,因为该对中第二个元素的类型是 ?
(如 Pair<?, ?>
)。它不知道该值实际上是一个 Integer。
As a follow-up
由于类型擦除,您无法使用不可具体化的元素类型创建数组。
可具体化的类型是一种在运行时关于该类型的一切都已知的类型。非泛型是可具体化的;所有类型参数都是通配符的泛型类型是可具体化的;其他泛型类型不是。
泛型和数组是不愉快的伙伴。如果您使用泛型,请改用 List
。
List<Pair<String, Integer>> s = new ArrayList<>();
s.add(new Pair<String, Integer>("a", 1));
s.add(new Pair<String, Integer>("b", 2));
s.add(new Pair<String, Integer>("c", 3));
添加到您的 Pair class 中的数据类型在运行时被删除。编译器只知道来自 getFirst()
和 getSecond()
的数据是 扩展 Object
的东西 ,但它不知道那是什么某事是具体的。
由于 Object
有一个 .toString()
方法,当您使用字符串连接运算符时会隐式调用该方法,因此 s[0].getFirst() + "!!!"
工作得很好。但是 <? extends Object>
(这是编译器在您使用它时所知道的关于您的类型的所有信息)作为加法运算符的左侧无效。
您可以通过将结果转换为整数来解决这个问题,如下所示:
System.out.println( (Integer) s[0].getSecond() + 2 );
但请注意,这只是您告诉编译器 "trust me, this is definitely an Integer"。