[英]Java 8 lower bounded wildcard
我正在准备OCP证书,我想到了一个较低的有界通配符的想法。 如果我理解正确的话,当我们想让Java知道“有界类型”总是可以添加到我们的通用集合时,使用下限有界通配符。
例如:
public static void addInteger(List<? super Integer> list, Integer i)
{
list.add(i);
}
public static void main(String[] args)
{
List<Number> list = new ArrayList<>();
addInteger(list, 100);
addInteger(list, 200);
System.out.println(list); // [100,200]
}
由于“?super Integer”表示类型必须是Integer或其超类,因此在列表中添加Integer将适用于每种情况。
但是,此代码仍然编译并运行正常:
public static void main(String[] args)
{
Predicate<? super String> pred = s -> s.startsWith("M"); // still compiles
System.out.println(pred.test("Mon")); // Output true
}
现在我们有一个谓词,它将采用1个参数,这是一个String或它的超类,但我们不确定它实际上是一个字符串与否(如果它只是一个对象怎么办?)。 但是,我们仍然可以访问startsWith()
方法,就像s
实际上是一个String。
为什么会这样? 请向我解释。
Predicate<? super String> pred
Predicate<? super String> pred
可以分配Predicate<String>
或Predicate<Object>
。 您正在为其分配一个允许的Predicate<String>
。 编译器推断s -> s.startsWith("M")
是一个Predicate<String>
因为你在lambda表达式中使用了String
方法。
例如,以下内容也将通过编译:
Predicate<? super String> pred = (Object o) -> o.hashCode() > 0;
您还可以看到以下传递编译:
Predicate<String> preds = s -> s.startsWith("M");
Predicate<Object> predo = (Object o) -> o.hashCode() > 0;
Predicate<? super String> pred = preds;
pred = predo;
即Predicate<? super String>
Predicate<? super String>
既可以分配Predicate<String>
,也可以分配Predicate<Object>
。
也就是说,注意pred.test()
只接受String
,而不接受任何Object
。 原因是pred
变量可以在运行时引用Predicate<Object>
或Predicate<String>
,并且两者都只接受String
。
你似乎对Predicate
对象实例的类型(由lambda创建)和pred
类型(对该对象的引用)之间的区别感到困惑。
由lambda创建的Predicate
实例的类型为Predicate<String>
。
参考pred
的对象的类型是Predicate<? super String>
Predicate<? super String>
,因此可以分配Predicate<Object>
和Predicate<String>
类型的值。 但是谓词的test
方法只能用String
对象调用!
那是什么? super String
? super String
绑定确保。
对象实例总是具有某些具体类型的类型参数,如Object
或String
。 只有引用可以具有通配符类型的类型参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.