英文:
Java Incompatible Types: Expected Number; Found Integer
问题
我有一个父类,其中有一个HashMap<ArrayList<Integer>, Number>
作为实例变量。这个类有各种不同的子类,这些子类需要将不同类型的数字(Integer、Double)用作该映射的值类型。当我尝试在子类的构造函数中初始化映射时,我会得到以下错误:
不兼容的类型。
所需类型:HashMap<ArrayList<Integer>, java.lang.Number>
找到类型:HashMap<ArrayList<Integer>,java.lang.Integer>
由于Integer扩展了Number,难道不应该因为多态性而起作用吗?
英文:
I have a parent class that has a HashMap<ArrayList<Integer>, Number>
as an instance variable. This class has various children that need to use different types of numbers (Integer, Double) as the value type for this map. When I try to initialize the map in the constructor of a subclass, I get the following error:
Incompatible types.
Required: HashMap<ArrayList<Integer>, java.lang.Number>
Found: HashMap<ArrayList<Integer>,java.lang.Integer>
Since Integer extends Number, shouldn't this work due to polymorphism?
答案1
得分: 2
使用:
HashMap<ArrayList<Integer>, ? extends Number>
而不是:
HashMap<ArrayList<Integer>, Number>
来声明:
HashMap<ArrayList<Integer>, 任何继承自Number的类型>
因此:
HashMap<ArrayList<Integer>, ? extends Number> hashMap1 =
new HashMap<ArrayList<Integer>, Integer>(); // 编译通过。
HashMap<ArrayList<Integer>, Number> hashMap2 =
new HashMap<ArrayList<Integer>, Integer>(); // 不能编译通过。
通常要记住,在泛型中,T<Parent>
不是 T<Child>
的超类型;相反,T<? extends Parent>
是 T<Child>
的超类型。
需要牢记的一点是捕获问题,也就是说,您将无法添加作为泛型类型参数使用的子类型的元素。
例如,这段代码:
ArrayList<Integer> arrayList = new ArrayList<>();
Integer integer = new Integer(5);
HashMap<ArrayList<Integer>, ? extends Number> hashMap
= new HashMap<ArrayList<Integer>, Integer>();
是可以正常工作的;
然而,随后这段代码:
hashMap.put(arrayList, new Integer(3)); // 不能正常工作。
将无法正常工作。
可以查看Java教程中的这一部分。
英文:
Use:
HashMap<ArrayList<Integer>, ? extends Number>
instead of:
HashMap<ArrayList<Integer>, Number>
to declare the super type of:
HashMap<ArrayList<Integer>, ANYTHING_EXTENDING_NUMBER>
Therefore:
HashMap<ArrayList<Integer>, ? extends Number> hashMap1 =
new HashMap<ArrayList<Integer>, Integer>(); //Compiles OK.
HashMap<ArrayList<Integer>, Number> hashMap2 =
new HashMap<ArrayList<Integer>, Integer>(); //Does not compile.
Generally, remember, that in Generics, T<Parent>
is not a super type of T<Child>
; rather T<? extends Parent>
is a super type of T<Child>
.
One thing to bear in mind is the Capture Problem, that is, you will not be able to add the elements of the subtype you use as a generic type argument.
For example, this:
ArrayList<Integer> arrayList = new ArrayList<>();
Integer integer = new Integer(5);
HashMap<ArrayList<Integer>, ? extends Number> hashMap
= new HashMap<ArrayList<Integer>, Integer>();
will work fine;
however, this afterwards:
hashMap.put(arrayList, new Integer(3)); //Does not work.
will not work.
Have a look at this section from Java tutorial.
答案2
得分: 0
传递一个Map<List<Integer>, Number>
应该可以使编译继续进行。
之所以不起作用的原因是Map<List<Integer>, Number>
不是Map<List<Integer>, Integer>
的子类型。一种理解方式是认识到Double是Number但不是Integer。因此,将double添加到第一个映射将成功,但对于第二个映射将失败。
顺便提一下,将Map的键设置为列表是很奇怪的。这应该被颠倒吗?
英文:
Passing a Map<List<Integer>, Number>
instead should allow compilation to continue.
The reason this doesn't work is because Map<List<Integer>, Number>
is not a sub-type of Map<List<Integer>, Integer>
. One way to understand this is by recognizing that a Double is a Number but not an Integer. As such, adding a double to the first map will succeed but will fail for the second map.
As an aside, it is strange to have the Map key be a list. Should this be flipped?
答案3
得分: 0
你可以尝试使用HashMap<ArrayList<Integer>, ? extends Number>
这样的映射定义,然后可以成功应用继承关系Integer extends Number
:
Map<Integer, Integer> imap = new HashMap<>(Map.of(1, 1, 2, 20, 3, 300));
print(imap); // 正常
Map<Integer, Double> dmap = new HashMap<>(Map.of(1, 1.25, 5, 10.0, 10, 300.0));
print(dmap); // 正常
Map<Integer, ? extends Number> nemap = imap; // 这是可以的
imap.put(4, 400); // 正常
// nemap.put(5, 500); // 失败:需要类型:捕获 ? extends Number
Map<Integer, ? super Number> nsmap = new HashMap<>();
nsmap.put(5, 500); // 正常!
nsmap.put(1, 10.0); // 也是正常的
print(nsmap); // 成功
System.out.println(nemap);
nemap = dmap;
System.out.println(nemap);
// -----
private static void print(Map<Integer, ? extends Number> map) {
map.entrySet().forEach(System.out::println);
}
英文:
You may try using map definition HashMap<ArrayList<Integer>, ? extends Number>
like this then inheritance Integer extends Number
can be applied successfully:
Map<Integer, Integer> imap = new HashMap<>(Map.of(1, 1, 2, 20, 3, 300));
print(imap); // ok
Map<Integer, Double> dmap = new HashMap<>(Map.of(1, 1.25, 5, 10.0, 10, 300.0));
print(dmap); // ok
Map<Integer, ? extends Number> nemap = imap; // that's ok
imap.put(4, 400); // ok
// nemap.put(5, 500); // fails: required type: capture ? extends Number
Map<Integer, ? super Number> nsmap = new HashMap<>();
nsmap.put(5, 500); // ok!
nsmap.put(1, 10.0); // ok too
print(nsmap); // succeeds
System.out.println(nemap);
nemap = dmap;
System.out.println(nemap);
// -----
private static void print(Map<Integer, ? extends Number> map) {
map.entrySet().forEach(System.out::println);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论