What's the difference between <?> and <? extends Object> in Java Generics? - java

I've seen the wildcard used before to mean any object - but recently saw a use of:
<? extends Object>
Since all objects extend Object, are these two usages synonymous?

<?> and <? extends Object> are synonymous, as you'd expect.
There are a few cases with generics where extends Object is not actually redundant. For example, <T extends Object & Foo> will cause T to become Object under erasure, whereas with <T extends Foo> it will become Foo under erasure. (This can matter if you're trying to retain compatibility with a pre-generics API that used Object.)
Source: http://download.oracle.com/javase/tutorial/extra/generics/convert.html; it explains why the JDK's java.util.Collections class has a method with this signature:
public static <T extends Object & Comparable<? super T>> T max(
Collection<? extends T> coll
)

Although <?> is supposed to be a shortcut for <? extend object>, there is a tiny difference between the two.
<?> is reifiable while <? extend object> is not. The reason they did this is to make it easier to distinguish reifiable type. Anything that looks like <? extends something>,<T>,<Integer> are nonreifiable.
For example, this code would work
List aList = new ArrayList<>();
boolean instanceTest = aList instanceof List<?>;
but this gives an error
List aList = new ArrayList<>();
boolean instancetest = aList instanceof List<? extends Object>;
for more info read Java generics and collections by Maurice Naftalin

<?> is a shorthand for <? extends Object>.
You may read below shared link for more details.
<?>
"?" denotes any unknown type, It can represent any Type at in code for. Use this wildcard if you are not sure about Type.
ArrayList<?> unknownList = new ArrayList<Number>(); //can accept of type Number
unknownList = new ArrayList<Float>(); //Float is of type Number
Note: <?> means anythings. So It can accept of Type which are not inherited from Object class.
<? extends Object>
<? extends Object> means you can pass an Object or a sub-class that extends Object class.
ArrayList<? extends Number> numberList = new ArrayList<Number>(); //Number of subclass
numberList = new ArrayList<Integer>(); //Integer extends Number
numberList = new ArrayList<Float>(); // Float extends Number
T – used to denote type
E – used to denote element
K – keys
V - values
N – for numbersRef:

Related

Incompatible return type while implementing interface method with generic wildcard return type [duplicate]

This compiles (1.6)
List<? extends Object> l = new ArrayList<Date>();
But this does not
List<List<? extends Object>> ll = new ArrayList<List<Date>>();
with the error of
Type mismatch: cannot convert from ArrayList<List<Date>> to List<List<? extends Object>>
Could someone explain why?
Thanks
EDIT: edited for being consequent
Well the explanations are correct, but I think it'd be a nice thing to add the actual working solution as well ;)
List<? extends List<? extends Object>>
Will work just fine, but obviously the use of such a collection is quite limited by the usual limitations of generic Collections (but then the same is true for the simpler List< ? extends Date >)
Because it would break type safety:
List<List<Object>> lo = new ArrayList<List<Object>>();
List<List<? extends Object>> ll = lo;
List<String> ls = new ArrayList<String>();
ll.add(ls);
lo.get(0).add(new Object());
String s = ls.get(0); // assigns a plain Object instance to a String reference
Suppose D is subtype of B, G<T> is a generic type
B x = new D(); // OK
G<B> y = new G<D>(); // FAIL
Now, G<Date> is a subtype of G<?>, therefore
G<?> x = new G<Date>(); // OK
G<G<?>> y = new G<G<Date>>(); // FAIL
When assigning to a variable (List<T>) with a non-wildcard generic type T, the object being assigned must have exactly T as its generic type (including all generic type parameters of T, wildcard and non-wildcard). In your case T is List<? extends Object>, which is not the same type as List<Date>.
What you can do, because List<Date> is assignable to List<? extends Object>, is use the wildcard type:
List<? extends List<? extends Object>> a = new ArrayList<List<Date>>();
<? extends Object>
means that the wildcard could be substituted only for those objects, that are subclass of Object class.
List<List<? extends Object>> ll = new ArrayList<List<Object>>();
gives you error of type mismatch because you are trying to assign a ArrayList of List of object of java class Object to a List that contains the List of any type of objects that are subclass of java class Object.
For more ref, have a look at the Wildcard documentation

Why in java generics List<Integer> is a subtype of List<? extends Integer>?

in java tutorial:
https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html
it denotes that List<Integer> is a subtype of List<? extends Integer>, which I find counter-intuitive, because ? extends Integer indicates any type that is Integer or subtype of Integer, what's the design considerations behind that?
quote:
https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html
The term List<Number> is more restrictive than List<? extends Number> because the former matches a list of type Number only, whereas the latter matches a list of type Number or any of its subclasses.
I'm also confused with List<? super Number> being subtype of List<? super Integer>.
Why in java generics List<Integer> is a subtype of List<? extends Integer>?
Because otherwise you wouldn't be able to do things such as:
List<Integer> list1 = new ArrayList<>();
List<? extends Integer> list2 = list1;
Personally, I would find the above resulting in an error to be the conter-intuitive scenario. When you have List<? extends Integer> all that's saying is that the List may contain Integer, some subtype of Integer1, or a mixture of Integer's subtypes1. A List<Integer> certainly meets those requirements.
The argument for List<? super Number> being a subtype of List<? super Integer> is very similar. If that wasn't the case then you couldn't do the following:
List<? super Number> list1 = new ArrayList<>();
List<? super Integer> list2 = list1;
All that List<? super Integer> means is the List is capable of consuming an object of type Integer or some supertype of Integer. A List<? super Number> meets those requirements.
Here are some links which may prove useful:
What is PECS (Producer Extends Consumer Super)?
Difference between <? super T> and <? extends T> in Java [duplicate]
How can I add to List<? extends Number> data structures?
I recommend browsing the linked/related sections of the above Q&As as well.
1. Saying "subtype of Integer" may be confusing since the class is final but hopefully it still makes sense.
I am surprised that there is a supertype/subtype relationship at all, given Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic? . However, since there is, I can only hazard my own thoughts/guesses as to why it is allowed and why this way around.
EDIT TO ADD: Further checking, I shouldn't have been surprised, since the relationships are the same as Dog and Animal - ie. List<Animal> is a subtype of List<? extends Animal>.
That being said, I imagine that it is to keep other references to these lists "safe". For example, consider some possible cases using :
public class PositiveInteger extends Integer {
Then we could have
List<Integer> listInteger = new ArrayList<>();
List<Integer> myIntegers = listInteger;
List<PositiveInteger> listPositiveInteger = new ArrayList<>();
List<PositiveInteger> myPositives = listPositiveInteger;
Now, the idea of supertypes and subtypes is that we can assign subtype references to supertypes, but not vice-versa. eg we can have :
Animal animal = myDog;
but not
Dog rex = someAnimal;
So let's apply that logic to our lists.
List<? extends Integer> positives = listInteger;
This is allowed as you said. The important thing to note is that our existing myIntegers variable is safe - it will still only ever contain Integers .
The only "danger" with this statement is that this allows positives.get(0) to potentially receive a negative Integer - but that's not really a danger at all (just a problem with our variable naming), since the language syntax here only refers to Integers, nothing about PositiveIntegers. So far as the language is concerned, we could equally well have :
List<? extends Integer> positives = new ArrayList<NegativeIntegers>();
Now what about if we allowed :
List<Integer> integers = listPositiveInteger;
Now THIS bit of the system is safe - but what about our myPositives variable ??? All users of myPositives are perfectly entitled to expect to only ever receive PositiveIntegers, but there is nothing stopping us from having :
integers.add(-123);
Since that is the same List Object as myPositives, then we're adding -123 to that List - a much more dangerous prospect implicitly affecting the rest of the system.
Try to look on ? super T subtyping like this:
<? super Number> is a wildcard for <Number> or <Serializable> or <Object>
<? super Integer> is a wildcard for <Integer> or <Number> or <Serializable> or <Object>
Integer can be placed in all possible <? super Number> so <? super Integer> can be a <? super Number> (IS A relationship, so <? super Number> is a subtype of <? super Integer>)
Number can't be placed in all possible <? super Integer> (you can't put any Number where Integer is expected) so <? super Number> can't be <? super Integer>

Java nested generic casting (? super Type) [duplicate]

How come one must use the generic type Map<?, ? extends List<?>> instead of a simpler Map<?, List<?>> for the following test() method?
public static void main(String[] args) {
Map<Integer, List<String>> mappy =
new HashMap<Integer, List<String>>();
test(mappy);
}
public static void test(Map<?, ? extends List<?>> m) {}
// Doesn't compile
// public static void test(Map<?, List<?>> m) {}
Noting that the following works, and that the three methods have the same erased type anyways.
public static <E> void test(Map<?, List<E>> m) {}
Fundamentally, List<List<?>> and List<? extends List<?>> have distinct type arguments.
It's actually the case that one is a subtype of the other, but first let's learn more about what they mean individually.
Understanding semantic differences
Generally speaking, the wildcard ? represents some "missing information". It means "there was a type argument here once, but we don't know what it is anymore". And because we don't know what it is, restrictions are imposed on how we can use anything that refers to that particular type argument.
For the moment, let's simplify the example by using List instead of Map.
A List<List<?>> holds any kind of List with any type argument. So i.e.:
List<List<?>> theAnyList = new ArrayList<List<?>>();
// we can do this
theAnyList.add( new ArrayList<String>() );
theAnyList.add( new LinkedList<Integer>() );
List<?> typeInfoLost = theAnyList.get(0);
// but we are prevented from doing this
typeInfoLost.add( new Integer(1) );
We can put any List in theAnyList, but by doing so we have lost knowledge of their elements.
When we use ? extends, the List holds some specific subtype of List, but we don't know what it is anymore. So i.e.:
List<? extends List<Float>> theNotSureList =
new ArrayList<ArrayList<Float>>();
// we can still use its elements
// because we know they store Float
List<Float> aFloatList = theNotSureList.get(0);
aFloatList.add( new Float(1.0f) );
// but we are prevented from doing this
theNotSureList.add( new LinkedList<Float>() );
It's no longer safe to add anything to the theNotSureList, because we don't know the actual type of its elements. (Was it originally a List<LinkedList<Float>>? Or a List<Vector<Float>>? We don't know.)
We can put these together and have a List<? extends List<?>>. We don't know what type of List it has in it anymore, and we don't know the element type of those Lists either. So i.e.:
List<? extends List<?>> theReallyNotSureList;
// these are fine
theReallyNotSureList = theAnyList;
theReallyNotSureList = theNotSureList;
// but we are prevented from doing this
theReallyNotSureList.add( new Vector<Float>() );
// as well as this
theReallyNotSureList.get(0).add( "a String" );
We've lost information both about theReallyNotSureList, as well as the element type of the Lists inside it.
(But you may note that we can assign any kind of List holding Lists to it...)
So to break it down:
// ┌ applies to the "outer" List
// ▼
List<? extends List<?>>
// ▲
// └ applies to the "inner" List
The Map works the same way, it just has more type parameters:
// ┌ Map K argument
// │ ┌ Map V argument
// ▼ ▼
Map<?, ? extends List<?>>
// ▲
// └ List E argument
Why ? extends is necessary
You may know that "concrete" generic types have invariance, that is, List<Dog> is not a subtype of List<Animal> even if class Dog extends Animal. Instead, the wildcard is how we have covariance, that is, List<Dog> is a subtype of List<? extends Animal>.
// Dog is a subtype of Animal
class Animal {}
class Dog extends Animal {}
// List<Dog> is a subtype of List<? extends Animal>
List<? extends Animal> a = new ArrayList<Dog>();
// all parameterized Lists are subtypes of List<?>
List<?> b = a;
So applying these ideas to a nested List:
List<String> is a subtype of List<?> but List<List<String>> is not a subtype of List<List<?>>. As shown before, this prevents us from compromising type safety by adding wrong elements to the List.
List<List<String>> is a subtype of List<? extends List<?>>, because the bounded wildcard allows covariance. That is, ? extends allows the fact that List<String> is a subtype of List<?> to be considered.
List<? extends List<?>> is in fact a shared supertype:
List<? extends List<?>>
╱ ╲
List<List<?>> List<List<String>>
In review
Map<Integer, List<String>> accepts only List<String> as a value.
Map<?, List<?>> accepts any List as a value.
Map<Integer, List<String>> and Map<?, List<?>> are distinct types which have separate semantics.
One cannot be converted to the other, to prevent us from doing modifications in an unsafe way.
Map<?, ? extends List<?>> is a shared supertype which imposes safe restrictions:
Map<?, ? extends List<?>>
╱ ╲
Map<?, List<?>> Map<Integer, List<String>>
How the generic method works
By using a type parameter on the method, we can assert that List has some concrete type.
static <E> void test(Map<?, List<E>> m) {}
This particular declaration requires that all Lists in the Map have the same element type. We don't know what that type actually is, but we can use it in an abstract manner. This allows us to perform "blind" operations.
For example, this kind of declaration might be useful for some kind of accumulation:
static <E> List<E> test(Map<?, List<E>> m) {
List<E> result = new ArrayList<E>();
for(List<E> value : m.values()) {
result.addAll(value);
}
return result;
}
We can't call put on m because we don't know what its key type is anymore. However, we can manipulate its values because we understand they are all List with the same element type.
Just for kicks
Another option which the question does not discuss is to have both a bounded wildcard and a generic type for the List:
static <E> void test(Map<?, ? extends List<E>> m) {}
We would be able to call it with something like a Map<Integer, ArrayList<String>>. This is the most permissive declaration, if we only cared about the type of E.
We can also use bounds to nest type parameters:
static <K, E, L extends List<E>> void(Map<K, L> m) {
for(K key : m.keySet()) {
L list = m.get(key);
for(E element : list) {
// ...
}
}
}
This is both permissive about what we can pass to it, as well as permissive about how we can manipulate m and everything in it.
See also
"Java Generics: What is PECS?" for the difference between ? extends and ? super.
JLS 4.10.2. Subtyping among Class and Interface Types and JLS 4.5.1. Type Arguments of Parameterized Types for entry points to the technical details of this answer.
This is because the subclassing rules for generics are slightly different from what you may expect. In particular if you have:
class A{}
class B extends A{}
then
List<B> is not a subclass of List<A>
It's explained in details here and the usage of the wildcard (the "?" character) is explained here.

Detail about the "super" wildcard in java generics

I have a question regarding generics:
Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>();
with super it's possible to instantiate a HashMap<Object,Object> for a <? super String>.
However then you can add only objects which extends String ( in this case only String itself).
Why don't they forbid by compilation error as well as happens with the extends wildcard.
I mean if once created a Map <Object, Object> it's possible only to add Strings.. why not forcing to create a Map<String, String> in the first place? (like it happens with the extends wildcard)
Again I know the difference between super and extends concerning generics. I would like just to know the details I have aboved-mentioned.
Thanks in advance.
Let's use List instead of Map for brevity.
Essentially, practical meaning of extends and super can be defined as follows:
List<? extends T> means "a List you can get T from"
List<? super T> means "a List you can put T into"
Now you can see that there is nothing special about extends - behavior of extends and super is completely symmetric:
List<? extends Object> a = new ArrayList<String>(); // Valid, you can get an Object from List<String>
List<? extends String> b = new ArrayList<Object>(); // Invalid, there is no guarantee that List<Object> contains only Strings
List<? super String> a = new ArrayList<Object>(); // Valid, you can put a String into List<Object>
List<? super Object> b = new ArrayList<String>(); // Invalid, you cannot put arbitrary Object into List<String>
I think you are thrown off because you picked a collection type. Collections are rarely used as consumers and thus a lower bound (? super X) is not put on their element types. A more appropriate example is predicate.
Consider a method such as <E> List<E> filter(List<? extends E> p, Predicate<? super E> p). It will take a list l and a predicate p and return a new list containing all elements of l which satisfy p.
You could pass in a List<Integer> and a Predicate<Number> which is satisfied by all multiples of 2.5. The Predicate<Number> would become a Predicate<? super Integer>. If it did not, you could not invoke filter as follows.
List<Integer> x = filter(Arrays.asList(1,5,8,10), Predicates.multipleOf(2.5));
Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>();
Since Java Generics are based on type erasure, with this line you didn't create a MashMap<Object,Object>. You just created an instance of the HashMap class; the type parameters get lost immediately after this line of code and all that stays is the type of your mappa1 variable, which doesn't even mention Object. The type of the new expression is assignment-compatible with the type of mappa1 so the compiler allows the assignment.
In general, the type parameters used with new are irrelevant and to address this issue, Java 7 has introduced the diamond operator <>. All that really matters is the type of mappa1, which is is Map<? super String, ? super String>; as far as the rest of your code is concerned, this is the type of the instantiated map.
The problem you're describing doesn't exist.
It is because your reference is declared as Map<? super String, ? super String>. But your actual object can hold any object since it's HashMap<Object,Object>
Map<? super String, ? super String> mappa1 = new HashMap<Object,Object>();
map1.put("", "");
//you can put only string to map1
//but you can do this
Map map2 = map1;
map2.put(23, 234);
the same can be described by a better example:
String a = "a".
a.length(); // legal.
Object b = a;
b.length() // compilation error

Java generics, nested collection of wildcard

This compiles (1.6)
List<? extends Object> l = new ArrayList<Date>();
But this does not
List<List<? extends Object>> ll = new ArrayList<List<Date>>();
with the error of
Type mismatch: cannot convert from ArrayList<List<Date>> to List<List<? extends Object>>
Could someone explain why?
Thanks
EDIT: edited for being consequent
Well the explanations are correct, but I think it'd be a nice thing to add the actual working solution as well ;)
List<? extends List<? extends Object>>
Will work just fine, but obviously the use of such a collection is quite limited by the usual limitations of generic Collections (but then the same is true for the simpler List< ? extends Date >)
Because it would break type safety:
List<List<Object>> lo = new ArrayList<List<Object>>();
List<List<? extends Object>> ll = lo;
List<String> ls = new ArrayList<String>();
ll.add(ls);
lo.get(0).add(new Object());
String s = ls.get(0); // assigns a plain Object instance to a String reference
Suppose D is subtype of B, G<T> is a generic type
B x = new D(); // OK
G<B> y = new G<D>(); // FAIL
Now, G<Date> is a subtype of G<?>, therefore
G<?> x = new G<Date>(); // OK
G<G<?>> y = new G<G<Date>>(); // FAIL
When assigning to a variable (List<T>) with a non-wildcard generic type T, the object being assigned must have exactly T as its generic type (including all generic type parameters of T, wildcard and non-wildcard). In your case T is List<? extends Object>, which is not the same type as List<Date>.
What you can do, because List<Date> is assignable to List<? extends Object>, is use the wildcard type:
List<? extends List<? extends Object>> a = new ArrayList<List<Date>>();
<? extends Object>
means that the wildcard could be substituted only for those objects, that are subclass of Object class.
List<List<? extends Object>> ll = new ArrayList<List<Object>>();
gives you error of type mismatch because you are trying to assign a ArrayList of List of object of java class Object to a List that contains the List of any type of objects that are subclass of java class Object.
For more ref, have a look at the Wildcard documentation

Categories