我正在尝试为我的自定义++
类型定义一个运算符Map
,如下所示:
@Override
public MutableMap<K, V> $plus$plus(Map<? extends K, ? extends V> map)
{
HashMap<K, V> copy = this.copy();
map.$plus$plus$eq(map);
return copy;
}
++=
运算符的定义如下:
public void $plus$plus$eq(Map<? extends K, ? extends V> map);
然而,编译器在map.$plus$plus$eq(map);
行上抱怨,出现以下疯狂错误:
The method $plus$plus$eq(Map<? extends capture#10-of ? extends K,
? extends capture#11-of ? extends V>) in the type
Map<capture#10-of ? extends K,capture#11-of ? extends V> is not
applicable for the arguments
(Map<capture#12-of ? extends K,capture#13-of ? extends V>)
正如您在此屏幕截图中看到的那样,Eclipse提供的解决方案都不起作用,但仅此一项甚至是有意义的:
我现在已经使用Java泛型了很长一段时间,甚至为自定义编程开发了我自己的通用类型系统(我目前正在尝试编写的库),但我之前从未遇到过这样的错误。
编辑 :有趣的是,将map
参数转换为原始类型(Map)
似乎可以解决问题。
map.$plus$plus$eq((Map) map);
但是,将强制转换更改为(Map<?, ?>)
(这是Eclipse的第二个解决方案所做的)会导致类似的错误。
答案 0 :(得分:4)
如果您使用原始类型Map
,它会起作用,但您会失去类型安全性。不要使用原始类型。它们只存在与Java 1.4及更旧版本的兼容性,它们没有泛型。
它不适用于通配符,因为编译器不知道通配符?
的确切类型。原因与您不能call add()
on a List<? extends T>
的问题相同。
请注意,通配符不意味着您可以使用键的类型扩展K
的任何类型的对象,并且值的类型扩展为V
。相反,它意味着您有一个映射,其中键是某些特定的,但未知类型K
,并且值是某些特定的,但未知类型V
。你不能在这样的地图上调用$plus$plus$eq
因为编译器不知道确切的类型,所以它无法检查它们。
原则上,您调用方法的Map
的通配符可能代表与您作为参数传递的Map
的通配符不同的类型 - 即使您可以在这种情况下,看它们必须是相同的,因为在这种情况下你使用相同的对象map
。
您可以使用类型参数而不是通配符来修复它:
@Override
public <KK extends K, VV extends V> MutableMap<K, V> $plus$plus(Map<KK, VV> map)
{
HashMap<K, V> copy = this.copy();
map.$plus$plus$eq(map);
return copy;
}
答案 1 :(得分:2)
这是一个也没有编译的简化示例。
class Foo<T> {
void bar(Foo<? extends T> foo) {
foo.bar(foo);
}
}
假设foo
和goo
的类型为Foo<? extends T>
。这意味着foo
的类型为Foo<U>
,其中U
是T
的子类型,goo
的类型为Foo<V>
,其中V
也是T
foo.bar(goo)
的子类型。您不希望V
起作用,因为U
可能不是foo.bar(foo)
的子类型。出于这个原因,foo
也没有编译。这看起来很疯狂,因为foo
和public void CancleSeat(String[][] SC, String can, int c, int r, int Seats, int an){
FillArray(SC);
if (can.equals("No")){
System.out.println("OK, no cancelations for you!");
}
else if (can.equals("Yes")){
System.out.println("How many seats would you like to cancel?");
an = scanner.nextInt();
for (int i = 0; i < an; i++){
System.out.println("What row is your seat in that you would like to cancle?");
r = scanner.nextInt();
r = r - 1;
System.out.println("What colum is your seat in that you would like to cancle?");
c = scanner.nextInt();
c = c -1;
if (SC[r][c].equals("-")){
System.out.println("That seat isn't researved pleas pick a different seat");
System.out.println("What row is your seat in that you would like to cancle?");
r = scanner.nextInt();
r = r - 1;
System.out.println("What colum is your seat in that you would like to cancle?");
c = scanner.nextInt();
c = c - 1;
}
else if (SC[r][c].equals("X") || SC[r][c].equals("x")){
SC[r][c] = "-";
}
}
}
}
是相同的实例,但参数是否适用仅取决于它们的编译时类型。