Java 8 lower bounded wildcard

Tran Anh Minh :

I'm preparing for OCP certificate, and I came across with the idea of a lower bounded wildcard. 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.

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.

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?). However, we can still access startsWith() method like s is actually a String.

Why does this happen? Please explain to me.

Eran :

Predicate<? super String> pred can be assigned either a Predicate<String> or a Predicate<Object>. You are assigning to it a Predicate<String>, which is allowed. The compiler infers that s -> s.startsWith("M") is a Predicate<String> since you are using a String method in the lambda expression.

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;

i.e. Predicate<? super String> can be assigned both a Predicate<String> and a Predicate<Object>.

That said, note that pred.test() will only accept Strings, and not any 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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=121503&siteId=1