Assume that you have a List
of numbers. The values in the List
can be of type Integer
, Double
etc. When you declare such a List
it is possible to declare it using a wildcard (?
) or without a wildcard.
final List<Number> numberList = Arrays.asList(1, 2, 3D);
final List<? extends Number> wildcardList = Arrays.asList(1, 2, 3D);
So, now I want to stream
over the List
and collect
it all to a Map
using the Collectors.toMap
(obviously the code below is just an example to illustrate the problem). Lets start off by streaming the numberList
:
final List<Number> numberList = Arrays.asList(1, 2, 3D, 4D);
numberList.stream().collect(Collectors.toMap(
// Here I can invoke "number.intValue()" - the object ("number") is treated as a Number
number -> Integer.valueOf(number.intValue()),
number -> number));
But, I can not do the same operation on the wildcardList
:
final List<? extends Number> wildCardList = Arrays.asList(1, 2, 3D);
wildCardList.stream().collect(Collectors.toMap(
// Why is "number" treated as an Object and not a Number?
number -> Integer.valueOf(number.intValue()),
number -> number));
The compiler complains on the call to number.intValue()
with the following message:
Test.java: cannot find symbol
symbol: method intValue()
location: variable number of type java.lang.Object
From the compiler error it is obvious that the number
in the lambda is treated as an Object
instead of as a Number
.
So, now to my question(s):
- When collecting the wildcard version of the
List
, why is it not working like the non-wildcard version of theList
? - Why is the
number
variable in the lambda considered to be anObject
instead of aNumber
?