【发布时间】:2017-02-05 10:48:02
【问题描述】:
我了解下界通配符存在的一个原因是,在添加新元素时集合不是不可变的。
例如
List<? extends Number> obj = new ArrayList<>();//Now this list is immutable
obj.add(new Integer(5));//Does not compile
List<? super Number> objTwo = new ArrayList<>();//This list is mutable
objTwo.add(new Integer(5));//Compiles
以下内容无法编译,因为我试图获取数字的长值。
Q1:我可以使用哪些方法?只有对象方法?:
public void testLowerBounds(List<? super Number> numbers){
if (!numbers.isEmpty()){
System.out.println(numbers.get(0).longValue());//Does not compile
}
}
我的问题是如何产生的: 我目前正在学习流,这本书指定了以下流方法:
Optional<T> min(Comparator<? super T> comparator)
并实现如下:
Stream<String> s = Stream.of("monkey", "ape", "bonobo");
Optional<String> min = s.min((s1, s2) -> s1.length()—s2.length());
Q2:比较器在使用时如何允许使用字符串方法?
如果我必须回答 Q2:我会说可选是指定“您必须向我传递具有通用类型“String”或实现“String”的 Comparator 的实现。我这样说是否正确?
期待您的回复。
【问题讨论】:
-
这似乎是两个不同的问题。关于第一个假设,当编译器阻止添加到列表时,它确实 not 意味着列表是不可变的。编译器只是遵守语言的静态类型检查规则。
-
同样
List没有longValue()方法。 -
您好 AR.3 感谢您的反馈。我已经改变了你是对的问题,我正在检查列表方法而不是内容。它们确实是两个不同的问题,我只是想解释一下问题的由来。我明白你所说的不可变,但现在它在逻辑上是不可变的,因为编译器不允许你添加到列表中。您现在对这两个问题都有答案了吗?
-
关于第一个问题,stackoverflow.com/questions/4343202/…已经详细回答了。
-
首先,编译器必须推断 lambda 表达式
(s1,s2)->...的类型,并限制它是Comparator<? super String>的子类型。推理规则选择Comparator<String>,这显然比Comparator<CharSequence>等其他选择更明智。一旦选择了 lambda 表达式的类型,我们现在就知道了 lambda 参数的类型s1,s2,它们都是String。因此,在 lambda 主体中,我们可以对它们调用String方法。请注意,在已知 lambda 参数类型之前,编译器无法查看 lambda 主体。
标签: java generics wildcard java-stream