假设您有一个List
数字。中的值List
可以是类型Integer
,Double
等等。List
声明时,可以使用通配符(?
)声明,也可以不使用通配符。
final List<Number> numberList = Arrays.asList(1, 2, 3D);
final List<? extends Number> wildcardList = Arrays.asList(1, 2, 3D);
所以,现在我想stream
在List
和collect
它所有的Map
使用Collectors.toMap
(显然下面的代码只是为了说明问题的例子)。让我们开始流式传输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));
但是,我不能在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));
编译器在调用时抱怨number.intValue()
以下消息:
Test.java:找不到符号
symbol:方法intValue()
位置:java.lang.Object类型的变量编号
从编译器错误中可以明显看出number
,将lambda中的视为Object
而不是Number
。
所以,现在我的问题是:
List
,为什么不能像的非通配符版本那样工作List
?number
lambda中的变量被认为是a Object
而不是a Number
?这是类型推断无法正确实现的原因。如果您明确提供type参数,则它可以按预期工作:
List<? extends Number> wildCardList = Arrays.asList(1, 2, 3D);
wildCardList.stream().collect(Collectors.<Number, Integer, Number>toMap(
number -> Integer.valueOf(number.intValue()),
number -> number));
这是一个已知的javac错误:推理不应将捕获变量映射到其上限。根据Maurizio
Cimadamore的说法,
尝试修复,然后因为在8中打破案例而退出,所以我们在8中进行了更保守的修复,而在9中完成了全部操作
显然,该修复程序尚未推出。
问题内容: 下列类定义了两种方法,它们在直观上都具有相同的功能。每个函数都有两个类型和一个布尔值的列表来调用,该值指定应将这些列表中的哪个分配给局部变量。 根据,有效而无效。它抱怨: 我知道查找包含三元运算符()的表达式类型的规则非常复杂,但是据我了解,它选择了最具体的类型,第二个和第三个参数都可以转换为该类型,而无需显式投。在这里,应该是,但不是。 我想解释一下为什么不是这种情况,最好参考 Ja
问题内容: 直到几天前,我才听说过野车,在读完我的老师的Java书籍后,我仍然不确定它的用途以及为什么需要使用它。 比方说,我有一个超类和几个子类都,,,等…现在我需要有动物名单,我首先想到的会是这样的: 相反,我的同事们建议采取以下措施: 为什么要使用通配符而不是简单的泛型? 假设我需要一个get / set方法,应该使用前一种还是后一种?它们有何不同? 问题答案: 声明局部变量时,通配符没有多
null 编译,我真的不明白为什么。基本上与第1行相同的问题。是的超类,如何将超类的成员放入此中? 编译。与第1行相同的问题。
在试图理解java泛型类型和通配符“?”的用法时,我尝试了以下方法: 我得到以下编译错误(使用Oracle JDeveloper作为IDE): 为什么上面的代码不能编译,而赋值却可以呢?另外,如果我想调用,什么是可接受的参数值?
问题内容: 我知道Java的泛型类型有各种各样的违反直觉的属性。特别是我不理解的一个,希望有人可以向我解释。为类或接口指定类型参数时,可以对其进行绑定,以使其必须使用来实现多个接口。但是,如果要实例化实际对象,则此方法不再起作用。很好,但是无法编译。考虑以下完整代码段: 似乎应该明确定义的语义-我想通过允许两种类型(而不只是一种类型)的交集,不会损失类型安全性。我敢肯定有一个解释。有谁知道它是什么
这是我试图理解的编译器行为的一个过度简化版本: 在上面的代码片段中,是一个类型范围比HouseCat接口允许的类型范围更广的引用,即: 如果我尝试执行类似的操作,编译器会告诉我不满足类型参数的约束。那么,,至少是潜在的。 编译器不会让我创建违反类型参数约束的实例,但我对它使用作为引用上限的行为感到困惑。在(,)之间有一个无效的类型范围,那么编译器为什么不拒绝这个引用定义呢? 澄清:我的问题不是关于