简体   繁体   English

Java 8下限有界通配符

[英]Java 8 lower bounded wildcard

I'm preparing for OCP certificate, and I came across with the idea of a lower bounded wildcard. 我正在准备OCP证书,我想到了一个较低的有界通配符的想法。 If I understand it correctly, the lower bounded wildcard is used when we want to let Java know the "bounded type" can always be added to our generic Collection. 如果我理解正确的话,当我们想让Java知道“有界类型”总是可以添加到我们的通用集合时,使用下限有界通配符。

For example: 例如:

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]

}

Since "? super Integer" indicates that the type must be an Integer or its superclass, adding an Integer to the list will work in each case. 由于“?super Integer”表示类型必须是Integer或其超类,因此在列表中添加Integer将适用于每种情况。

However, this code still compiles and runs like normal: 但是,此代码仍然编译并运行正常:

public static void main(String[] args)
{   
    Predicate<? super String> pred = s -> s.startsWith("M"); // still compiles
    System.out.println(pred.test("Mon")); // Output true

}

Now we have a Predicate that will take 1 parameter which is a String or its super class, but we're not sure it's actually a String or not (What if it's just an Object?). 现在我们有一个谓词,它将采用1个参数,这是一个String或它的超类,但我们不确定它实际上是一个字符串与否(如果它只是一个对象怎么办?)。 However, we can still access startsWith() method like s is actually a String. 但是,我们仍然可以访问startsWith()方法,就像s实际上是一个String。

Why does this happen? 为什么会这样? Please explain to me. 请向我解释。

Predicate<? super String> pred Predicate<? super String> pred can be assigned either a Predicate<String> or a Predicate<Object> . Predicate<? super String> pred可以分配Predicate<String>Predicate<Object> You are assigning to it a Predicate<String> , which is allowed. 您正在为其分配一个允许的Predicate<String> The compiler infers that s -> s.startsWith("M") is a Predicate<String> since you are using a String method in the lambda expression. 编译器推断s -> s.startsWith("M")是一个Predicate<String>因为你在lambda表达式中使用了String方法。

For example, the following will also pass compilation: 例如,以下内容也将通过编译:

Predicate<? super String> pred = (Object o) -> o.hashCode() > 0;

You can also see that the following passes compilation: 您还可以看到以下传递编译:

Predicate<String> preds = s -> s.startsWith("M");
Predicate<Object> predo = (Object o) -> o.hashCode() > 0;
Predicate<? super String> pred = preds;
pred = predo;

ie Predicate<? super String> Predicate<? super String> Predicate<? super String> can be assigned both a Predicate<String> and a Predicate<Object> . Predicate<? super String>既可以分配Predicate<String> ,也可以分配Predicate<Object>

That said, note that pred.test() will only accept String s, and not any Object . 也就是说,注意pred.test()只接受String ,而不接受任何Object The reason is that the pred variable can reference either a Predicate<Object> or Predicate<String> at runtime, and only a String is acceptable by both. 原因是pred变量可以在运行时引用Predicate<Object>Predicate<String> ,并且两者都只接受String

Your seem to be confused about the difference between the type of the Predicate object instance (that is created by the lambda) and type of pred , the reference to that object. 你似乎对Predicate对象实例的类型(由lambda创建)和pred类型(对该对象的引用)之间的区别感到困惑。

  • The Predicate instance that is created by the lambda has type Predicate<String> . 由lambda创建的Predicate实例的类型为Predicate<String>

  • The reference pred to the object is of type Predicate<? super String> 参考pred的对象的类型是Predicate<? super String> Predicate<? super String> , and can thus be assigned values of both type Predicate<Object> and Predicate<String> . Predicate<? super String> ,因此可以分配Predicate<Object>Predicate<String>类型的值。 But the test method of the predicate can only be called with String objects! 但是谓词的test方法只能用String对象调用!

    That's what the ? super String 那是什么? super String ? super String bound ensures. ? super String绑定确保。

Object instances always have type parameters of some concrete type, like Object or String . 对象实例总是具有某些具体类型的类型参数,如ObjectString Only references to can have type parameters of wildcard types. 只有引用可以具有通配符类型的类型参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM