Assume we have a predicate declared as Predicate<? super SomeClass>. I would naively expect it to be applicable to any superclass of SomeClass up the hierarchy, including Object.
However this predicate is not applicable to Object. I get the following error:
The method test(capture#3-of ? super SomeClass) in the type Predicate is not applicable for the arguments (Object)
Demo.
Why is Predicate<? super SomeClass> not applicable to an instance of Object?
The code:
import java.util.*;
import java.lang.*;
import java.io.*;
import java.net.URL;
import java.util.function.Predicate;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
Predicate<? super URL> p = u -> u.getFile().isEmpty();
p.test(new Object());
}
}
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.
Consider the broader example:
Predicate<? super Integer> p;
In this situation, any of the following assignments is valid, right?
p = (Predicate<Integer>) i -> true; // but, only Integer can be applied
p = (Predicate<Number>) n -> true; // Number and its sub-classes (Integer, Double...)
p = (Predicate<Object>) o -> true; // any type
So, if in the end it is:
Predicate<? super Integer> p = (Predicate<Integer>) i -> true;
Then, certainly, neither Number nor Object could not be applied to the predicate.
To guarantee type safety, a compiler allows only those types, which are valid for any of the possible assignments to the Predicate<? super Integer> - so, only Integer in this particular example.
Changing the lower bound from Integer to Number extends the boundaries respectively:
Predicate<? super Number> p = (Predicate<Number>) n -> true;
Now, the predicate can be applied to the Number and any of its sub-classes : Integer, Double etc.
Summarizing
The only types which can be applied to the Predicate<? super SomeClass> without breaking a type safety guarantees: the lower bound itself and its sub-classes.
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
The java tutorial pages provides some good information about upper / lower bounded wildcards when using generics.
It also provides some guidelines for using wildcards which can help decide which wildcard you should use:
An "In" Variable
An "in" variable serves up data to the code. Imagine a copy method with two arguments: copy(src, dest). The src argument provides the
data to be copied, so it is the "in" parameter. An "Out" Variable
An "out" variable holds data for use elsewhere. In the copy example, copy(src, dest), the dest argument accepts data, so it is the
"out" parameter.
Of course, some variables are used both for "in" and "out" purposes —
this scenario is also addressed in the guidelines.
You can use the "in" and "out" principle when deciding whether to use
a wildcard and what type of wildcard is appropriate. The following
list provides the guidelines to follow: Wildcard Guidelines:
An "in" variable is defined with an upper bounded wildcard, using the extends keyword.
An "out" variable is defined with a lower bounded wildcard, using the super keyword.
In the case where the "in" variable can be accessed using methods defined in the Object class, use an unbounded wildcard.
In the case where the code needs to access the variable as both an "in" and an "out" variable, do not use a wildcard.
These guidelines do not apply to a method's return type. Using a
wildcard as a return type should be avoided because it forces
programmers using the code to deal with wildcards.
This is quite a complex subject. These ? extends T and ? super T declarations are rather supposed to create a "matching" between classes.
If a class defines a method taking a Consumer, say something like Iterable<T>.foreach(), it defines this consumer to accept everything which can take a T. Thus, it defines it as forEach(Consumer<? super T> action). Why? Because an Iterator<Integer>'s foreach() can be called with a Consumer<Number> or even a Consumer<Object>. This is something which wouldn't be possible without the ? super T.
OTOH, if a class defines a method taking a Supplier, say something like addFrom, it defines this supplier to supply everything which is a T. Thus, it defines it as addFrom(Supplier<? extends T> supplier). Why? Because a ThisClass<Number>'s addFrom() can be called with a Supplier<Integer> or a Supplier<Double>. This is something which wouldn't be possible without the ? extends T.
Maybe a better example for the latter: List<E>.addAll() which takes a Collection<? extends E>. This makes it possible to add the elements of a List<Integer> to a List<Number>, but not vice versa.
Related
As far as I can tell, this is a generic method (as opposed to a method of a generic class):
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor)
I'm curious how Java decides the parameter types for any keyExtractor lambda that I pass in, given that T is parameterized.
If there was some extra information, like if T was restricted to being T super Z for some concrete Z, then it would make sense that you can only pass in subclasses of Z, and thus inside the keyExtractor lambda I can typecheck as if a class Z object has been passed in.
But given that there's no information available on T, how does this even work?
Does it decide based on the context of how the lambda being returned by comparing is being used?
I'm very confused, but maybe I don't fully understand generics and lambdas.
Any clarification would be appreciated, thanks!
But given that there's no information available on T, how does this even work?
If there really is no information available on T, then it defaults to Object, such as when you call comparing as a standalone statement:
Comparator.comparing(x -> { ... });
The compile time type of x will be Object.
But you rarely call comparing like that, right? You usually pass its return value into method, or at least assign it to a variable of a known type first:
someMethod(Comparator.comparing(x -> { ... }));
// or
Comparator<SomeType> c = Comparator.comparing(x -> { ... });
In both of these situations, there are more information to determine what T is. Notice that the return type of comparing is Comparator<T>, so if someMethod above accepts a Comparator<SomeType>, the type inference engine can work out that T must be SomeType in both cases.
Also note that you can specify the parameter's type in a lambda, this helps infer T as well:
Comparator.comparing((SomeType x) -> { ... })
question about Wildcard
Example:Student extends Person
Person person = new Person();
Student student = new Student();
List<? super Student> list = new ArrayList<>();
list.add(student); // success
list.add(person); // compile error
List<? extends Person> list2 = new ArrayList<>();
list2.add(person); // compile error
list2.add(student);// compile error
I have read the answer below a question "capture#1-of ? extends Object is not applicable"
You are using generic wildcard. You cannot perform add operation as class type is not determinate. You cannot add/put anything(except null) -- Aniket Thakur
Official doc:The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype
But why could list.add(student) compile successfully ?
Design of java.util.function.Function
public interface Function<T, R>{
//...
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
}
Why before is designed to Function<? super V, ? extends T> rather than Function<V,T> when the type of return is Function<V,R> and type of the input is V ? (It still can pass compile and use flexibly)
To understand these questions, you have to understand how generics work with subtyping (which is explicitly denoted in Java using the extends keyword). Andreas mentioned the PECS rules, which are their representations in Java.
First of all, I want to point out that the codes above can be corrected by a simple cast
ArrayList<? super Student> list = new ArrayList<>();
list.add(new Student());
ArrayList<Person> a = (ArrayList<Person>) list; // a covariance
a.add(new Person());
And compiles & runs well (rather than raising any exceptions)
The reason is simple, when we have a consumer (which takes some objects and consume them, such as the add method), we expect it to take objects of type no more than(superclasses) the type T we specified, because the process of consuming needs possibly any member(variables, methods etc.) of the type it wants, and we want to ensure that type T satisfy all the members the consumer requires.
On the contrary, a producer, which produces objects for us (like the get method), has to supply objects of type no less than the specified type T so that we can access any member that T has on the object produced.
These two are closely related to subtyping forms called covariance and contravariance
As for the second question, you can refer to the implementation of Consumer<T> as well (which is somewhat simpler):
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
the reason why we need this ? super T is that: when we are combining two Consumers using the method andThen, suppose that the former Consumer takes an object of type T, we expect the later to take a object of type no more than T so it would not try to access any member that T doesn't have.
Therefore, rather than simply writing Consumer<T> after but Consumer<? super T> after, we allow the former consumer (of type T) to be combined with a consumer that takes an object not exactly of type T, but maybe smaller then T, by the convenience of covariance. That makes the following codes sound:
Consumer<Student> stu = (student) -> {};
Consumer<Person> per = (person) -> {};
stu.andThen(per);
The compose method of type Function also applies, by the same consideration.
IMO This is probably the most complex concept in vanilla Java. So let's break this down a bit. I'll start with your second question.
Function<T, R> takes an instance t of type T and returns an instance r of type R. With inheritance that means that you could supply an instance foo of type Foo if Foo extends T and similarly return bar of type Bar if Bar extends R.
As a library maintainer who wants to write a flexible generic method, it's hard, and actually impossible, to know in advance all the classes which might be used with this method which extend T and R. So how are we going to write a method that handles them? Further, the fact that these instances have types which extend the base class is none of our concern.
This is where the wildcard comes in. During the method call we say that you can use any class which meets the envelope of the required class. For the method in question, we have two different wildcards using upper and lower bounded generic type parameters:
public interface Function<T, R>{
default <V> Function<V, R> compose(Function<? super V, ? extends T> before)
Lets now say that we want to take advantage of this method... for the example lets define some basic classes:
class Animal{}
class Dog extends Animal{}
class Fruit{}
class Apple extends Fruit{}
class Fish{}
class Tuna extends Fish{}
Imagine our function and transformation is defined as below:
Function<Animal, Apple> base = ...;
Function<Fish, Animal> transformation = ...;
We can combine these functions using compose to create a new function:
Function<Fish, Apple> composed = base.compose(transformation);
This is all fine and dandy, but now imagine that in the desired output function we actually only want to use Tuna as the input. If we did not use the lower-bounded ? super V as the input type parameter for the Function we pass to compose then we would get a compiler error:
default <V> Function<V, R> compose(Function<V, ? extends T> before)
...
Function<Tuna, Apple> composed = base.compose(transformation);
> Incompatible types:
> Found: Function<Fish, Apple>, required: Function<Tuna, Apple>
This happens because the return type for the call to compose specifies V as Tuna while transformation on the other hand specifies its "V" as Fish. So now when we try to pass transformation to compose the compiler requires transformation to accept a Tuna as its V and of course Tuna does not identically match Fish.
On the other hand, the original version of the code (? super V) allows us to treat V as a lower bound (i.e. it allows "contravariance" vs. "invariance" over V). Instead of encountering a mismatch between Tuna and Fish the compiler is able to successfully apply the lower bound check ? super V which evaluates to Fish super Tuna, which is true since Tuna extends Fish.
For the other case, imagine our call is defined as:
Function<Animal, Apple> base = ...;
Function<Fish, Dog> transformation = ...;
Function<Fish, Apple> composed = base.compose(transformation);
If we did not have the wildcard ? extends T then we would get another error:
default <V> Function<V, R> compose(Function<? super V, T> before)
Function<Fish, Apple> composed = base.compose(transformation);
// error converting transformation from
// Function<Fish, Dog> to Function<Fish, Animal>
The wildcard ? extends T allows this to work as T is resolved to Animal and the wildcard resolves to Dog, which can satisfy the constraint Dog extends Animal.
For your first question; these bounds really only work in the context of a method call. During the course of the method, the wildcard will be resolved to an actual type, just as ? super V was resolved to Fish and ? extends T was resolved to Dog. Without the information from the generic signature, we would have no way for the compiler to know what class can be used on the type's methods, and therefore none are allowed.
<D extends com.j256.ormlite.dao.Dao<T,?>,T> D getDao(Class<T> clazz)
I am not able to understand above statement
getDao(Class clazz) returns D
D having following constraints
D extends com.j256.ormlite.dao.Dao<T,?>
and extra ,T i am not able to understand.
Could you please explain it ?
This method has two type parameters, D and T, with D having an additional extends constraint, depending on T. Don't get confused by this <T,?>,T syntax; the ,T does not belong to the constraint, but is the second parameter, telling Java that T is not the name of a concrete class.
If you add a space or swap the parameters, it will be clearer. Here's a similar, but somewhat simpler example. These method signatures are all equivalent:
<D extends List<T>,T> D createListOf(Class<T> clazz) // your version
<D extends List<T>, T> D createListOf(Class<T> clazz) // extra space
<T, D extends List<T>> D createListOf(Class<T> clazz) // different order
Keep in mind that, even though it may seem apparent that T is another type parameter, this is not clear to Java. There could be an actual class named T, so we have to be explicit that T is a type parameter.
class T { ... } // this T is not what I want!
Conversely, type parameters are not restricted to single characters. You could also have a type parameter called Foo, or even String, if you want to utterly confuse your co-workers. Maybe that makes clear why the declaration of all type parameters using <...> is necessary.
// just a deterrent example; don't do this! String as parameter, not class
<String, Foo extends List<String>> Foo createListOf(Class<String> clazz)
This method will:
Return an object of type D
Where D is or extends com.j256.ormlite.dao.Dao, parametrized with an object of type T or extending/implementing T and an unknown type parameter
If given as argument a class of type T
It uses a lot of generic abstraction, which is not surprising given it delivers a DAO (Data Access Object).
According to the book "Effective Java" of Joshua Bloch there is a rule about how/when use the bounded wildcards in generics. This rule is PECS (Producer-Extends, Comsumer-Super). When I study the following example:
Stack<Number> numberStack = new Stack<Number>();
Iterable<Integer> integers = ... ;
numberStack.pushAll(integers);
I understand that this rule fits perfect in this example. I have to declare the method pushAll as the following sample:
// Wildcard type for parameter that serves as an E producer
public void pushAll(Iterable<? extends E> src) {
for (E e : src)
{
push(e);
}
}
But what happens if I have the following example?
Stack<Integer> integerStack = new Stack<Integer>();
Iterable<Number> numbers = ... ;
integerStack.pushAll(numbers);
I have to declare the pushAll as it follows:
public void pushAll(Iterable<? super E> src) {
for (E e : src)
{
push(e);
}
}
According to PECS rule the above declaration is wrong. But I want to have a Stack of Integers and pass to this Stack a Number. Why not to do it?
Why should I always use the extends keyword? Why using super is wrong?
Of course the same stands for the comsumer's point of view. Why a consumer should always be super?
PS: To be more specific you can find this above example at the sector "Item 28" of the referred book.
When you declare a Stack<Foo> you mean a Stack of Foos, or subclasses of Foo. As an example, you would expect to be able to put a String in a Stack<Object>. The other way is not true, you should not be able to insert another Object, in a Stack<String>.
In your example you declare a Stack<Integer>. You should be able to put Integers in this stack, but not other Numbers (like a Double), which you would if you declared the parameter <? super E>. That's why the put-method should have a paramter of the type <? extends E>.
Trying to store arbitrary numbers in a Stack can't possibly work, since a Number could be something other that an Integer. So your example doesn't make much sense.
You would use super when the object asts as a consumer, i.e. when instances of the generic type of the object are passed as arguments to methods of the object. For example:
Collections.sort(List<T>, Comparator<? super T>)
In this example, the sort method takes T instances from the collection, and passes them as argument to the compare(T o1, T o2) of the comparator.
Contrast this to your first example, where the Iterable src is a producer. The pushAll() method calls a method of the Iterable which roduces (i.e. returns) instances of T. In this case, the iterable is a producer, hence the use of ? extends T
In the pushAll method, you are not passing type E, but any type that extends E. So, instead of passing an Iterable of Numbers, you can pass any Iterable of a type that extends Number.
The original example uses a Number type because you can then pass any type that is a subclass of Number, like Integer, BigDecimal and so on.
In your example, you are doing it the other way around. You are using Integer to declare your Stack. Therefore, pushAll will only be able to accept those classes that are extended by Integer. You will not be able to use Numbers (or any other class, because Integer is a final class).
First thing to notice is that Integer extends Number, so you shouldn't be pushing Number objects into a Stack of Integers. However, the first sample will work with Integers, Floats, BigDecimal and all other Number subclasses.
Your example doesn't make much sense. A construct like <? extends Number> means that Number and every type is allowed which inheits from Number. So you define an upper and a lower boundary, from type Number down to the most specific one. The other way round, <? super Number> means that Number and any of its supertyes are allowed. Since Number extends Object and implements Serializable the following three types are allowed:
java.lang.Number
java.lang.Object
java.io.Serializable
In your example you declare the generic type Stack<Integer>. Let's consider the following.
Your Stack is never be able to hold items of any super type of Integer
Your Stack is never be able to hold items of any subtype of Integer, since Integer class is final and thus it can't be subclassed.
So, if you want to declare the generic type Stack<Integer>, your iterable is of type Iterable<Integer> and thus your Stack can only hold items of type Integer. You are totally right with the mnemonic PECS, but this only works if you have choosen a concrete type which has at least one super type and at least one subtype.
The code below makes complete sense to me - its about adding an element of some type which is supertype of type T and type S is definitely such a super type , so why the compiler refuses to add 'element' into the collection ?
class GenericType<S,T extends S>{
void add1(Collection<? super T> col ,S element ){
col.add(element); // error
// The method add(capture#9-of ? super T) in the type
// Collection<capture#9-of ? super T> is not applicable for the arguments (S)
}
}
Thake an example, if A <- B <- C where <- means that is the supertype, then if S = B and T = C you cannot add an instance of S to a collection of T.
A supertype of T may be the supertype or a subtype of another supertype of T (in this case S).
Collection<? super T> does not mean "a collection that can contain T and any superclass of it" - it's actually not possible to formulate that restriction. What it means is "a collection that can only contain instances of some specific class which is a superclass of T" - basically it ensures that you can add a T to the collection.
The method can be called with a Collection<T>, yet you want to add an S to it.
new GenericType<Object,Integer>().add1(new ArrayList<Integer>(), "");
You are trying to put an element of type S into a collection of type T. Generics aren't polymorphic.
You have to take notice of 2 problems here. you are trying to create an Collection of type concreteObject extends Object and are adding an object
So when you have
Car extends Vehicle{}
ElectricCar extends Car{}
you are trying to do
Collection<? extends Car> collection;
collection.add(new Vehicle());
The second problem lies with the non-polymorphism nature of Generics. See this great explanation -> Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?