Why is Predicate<? super SomeClass> not applicable to Object?
The Predicate already has a type. The type the predicate accepts can't be decided at the point when you try and call it. It has a type, and that type is some superclass of X; it's just unknown.
If I have a Predicate<Collection>
, that could be referenced as a Predicate<? super List>
. But that doesn't mean that it will accept any Object
. The ? extends X
generic type doesn't mean it will accept anything matching the given constraints. It means it is a predicate for some kind of unknown type that matches the given constraints.
Predicate<? super List> predicate = Collection::isEmpty;
predicate.test(new Object()); // Should this be valid? Clearly not
For a Predicate<? super SomeClass>
variable, you can assign a Predicate<SomeClass>
instance, or a Predicate<Object>
instance.
However, you can't pass an Object
to the test()
method of a Predicate<SomeClass>
. You can only pass a SomeClass
instance.
Therefore you can't pass an Object
to the test()
method of a Predicate<? super SomeClass>
Consider the following:
Predicate<URL> p1 = u -> u.getFile().isEmpty();
Predicate<? super URL> p2 = p1;
p2
is referring to a Predicate<URL>
, so you can't pass a new Object()
to its test()
method.
In other words, in order for p.test(new Object())
to be accepted by the compiler, it must be valid for any Predicate
that can be assigned to the Predicate<? super URL> p
variable. Since the Predicate<URL>
Predicate
can be assigned to that variable, and its test()
method cannot accept an Object
, p.test(new Object())
cannot be accepted by the compiler.
BTW, in your specific example, you are creating a Predicate<URL>
, and URL
is a final class. Therefore, you should simply declare it as:
Predicate<URL> p = u -> u.getFile().isEmpty();
There's no reason for ? super
or ? extends
.