Java 不兼容的类型:期望 Number;找到 Integer

huangapple go评论78阅读模式
英文:

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&lt;ArrayList&lt;Integer&gt;, ? extends Number&gt;

instead of:

HashMap&lt;ArrayList&lt;Integer&gt;, Number&gt;

to declare the super type of:

HashMap&lt;ArrayList&lt;Integer&gt;, ANYTHING_EXTENDING_NUMBER&gt;

Therefore:

HashMap&lt;ArrayList&lt;Integer&gt;, ? extends Number&gt; hashMap1 = 
  new HashMap&lt;ArrayList&lt;Integer&gt;, Integer&gt;(); //Compiles OK.
HashMap&lt;ArrayList&lt;Integer&gt;, Number&gt; hashMap2 = 
  new HashMap&lt;ArrayList&lt;Integer&gt;, Integer&gt;(); //Does not compile.

Generally, remember, that in Generics, T&lt;Parent&gt; is not a super type of T&lt;Child&gt;; rather T&lt;? extends Parent&gt; is a super type of T&lt;Child&gt;.

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&lt;Integer&gt; arrayList = new ArrayList&lt;&gt;();
Integer integer = new Integer(5);

HashMap&lt;ArrayList&lt;Integer&gt;, ? extends Number&gt; hashMap
    = new HashMap&lt;ArrayList&lt;Integer&gt;, Integer&gt;();

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&lt;List&lt;Integer&gt;, Number&gt;应该可以使编译继续进行。

之所以不起作用的原因是Map&lt;List&lt;Integer&gt;, Number&gt;不是Map&lt;List&lt;Integer&gt;, Integer&gt;的子类型。一种理解方式是认识到Double是Number但不是Integer。因此,将double添加到第一个映射将成功,但对于第二个映射将失败。

顺便提一下,将Map的键设置为列表是很奇怪的。这应该被颠倒吗?

英文:

Passing a Map&lt;List&lt;Integer&gt;, Number&gt; instead should allow compilation to continue.

The reason this doesn't work is because Map&lt;List&lt;Integer&gt;, Number&gt; is not a sub-type of Map&lt;List&lt;Integer&gt;, Integer&gt;. 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&lt;ArrayList&lt;Integer&gt;, ? extends Number&gt;这样的映射定义,然后可以成功应用继承关系Integer extends Number

Map&lt;Integer, Integer&gt; imap = new HashMap&lt;&gt;(Map.of(1, 1, 2, 20, 3, 300));
print(imap); // 正常
Map&lt;Integer, Double&gt; dmap = new HashMap&lt;&gt;(Map.of(1, 1.25, 5, 10.0, 10, 300.0));
print(dmap); // 正常

Map&lt;Integer, ? extends Number&gt; nemap = imap;  // 这是可以的
imap.put(4, 400); // 正常
// nemap.put(5, 500); // 失败:需要类型:捕获 ? extends Number

Map&lt;Integer, ? super Number&gt; nsmap = new HashMap&lt;&gt;();
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&lt;Integer, ? extends Number&gt; map) {
    map.entrySet().forEach(System.out::println);
}
英文:

You may try using map definition HashMap&lt;ArrayList&lt;Integer&gt;, ? extends Number&gt; like this then inheritance Integer extends Number can be applied successfully:

Map&lt;Integer, Integer&gt; imap = new HashMap&lt;&gt;(Map.of(1, 1, 2, 20, 3, 300));
print(imap); // ok
Map&lt;Integer, Double&gt; dmap = new HashMap&lt;&gt;(Map.of(1, 1.25, 5, 10.0, 10, 300.0));
print(dmap); // ok

Map&lt;Integer, ? extends Number&gt; nemap = imap;  // that&#39;s ok
imap.put(4, 400); // ok
// nemap.put(5, 500); // fails: required type: capture ? extends Number

Map&lt;Integer, ? super Number&gt; nsmap = new HashMap&lt;&gt;();
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&lt;Integer, ? extends Number&gt; map) {
    map.entrySet().forEach(System.out::println);
}

huangapple
  • 本文由 发表于 2020年9月26日 02:03:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/64069239.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定