I am reading multi-level wild cards from AngelikaLangerGenericsFaq. I am pretty confused about the syntax. The document says
The type
Collection<Pair<String,?>>
is a concrete instantiation of the generic Collection interface. It is a heterogenous collection of pairs of different types. It can contain elements of typePair<String,Long>
,Pair<String,Date>
,Pair<String,Object>
,Pair<String,String>
, and so on and so forth. In other words,Collection<Pair<String,?>>
contains a mix of pairs of different types of the formPair<String,?>
.The type
Collection<? extends Pair<String,?>>
is a wildcard parameterized type; it does NOT stand for a concrete parameterized type. It stands for a representative from the family of collections that are instantiations of the Collection interface, where the type argument is of the formPair<String,?>
. Compatible instantiations areCollection<Pair<String,Long>>
,Collection<Pair<String,String>>
,Collection<Pair<String,Object>>
, orCollection<Pair<String,?>>
. In other words, we do not know which instantiation of Collection it stands for.As a rule of thumb, you have to read multi-level wildcards top-down.
I am confused about the following points.
Can someone elaborate these points. Thanks.
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).
Wildcards are special characters that can stand in for unknown characters in a text value and are handy for locating multiple items with similar, but not identical data. Wildcards can also help with getting data based on a specified pattern match.
Can someone elaborate on these three quotes with example. I am totally lost into the syntax
Well, it wouldn't make sense to write those 3 quotes again here, as I can't give a better explanation than that. Instead, I will try to answer your other questions below, then possibly you will understand the answer to this one too. If not, you can ask your query again and I'll try to elaborate a little further.
Document says, para-1 is the concrete instantiation of a generic type and other is not the concrete instantiation? How is that?
A concrete instantiation is the one in which all the type arguments are concrete types, and are known at compile time. For e.g., List<String>
is a concrete instantiation, because String
is a concrete type. Its type is known at compile time. Whereas, List<? extends Number>
is not a concrete type, because ? extends Number
can be any type that extends Number
. So, its type is unknown at compile time. Similarly, Map<String, Integer>
is a concrete instantiation of generic type Map<K, V>
.
In the case of multi-level type parameters, List<List<? extends Number>>
, the outer List
is a concrete instantiation of List<E>
, because the type of elements is known to be a List
at compile time, although the inner List
is a wildcard instantiation, as the type of elements stored can be Integer
, Double
, any subclass of Number
. But that paragraph is talking about the outer type only. And the outer type can only contain List
type.
That's why the first paragraph said, it's a heterogenous collection of Pair
, because the actual type parameter of Pair
can be anything, but that is certain to be Pair
and nothing else.
What does it mean to read the wild-cards top down?
Talking in layman's term, it means from left-to-right. While determining the type of the parameterized type, you first see the outermost type parameter. Then if that type parameter is itself a parameterized type, then you move onto the type parameters of that parameterized type. So, we read the type parameters, from left-to-right.
What is the advantage of multi-level wild cards?
Suppose you want to create a List of List of Fruits. Now your inner List
can contain any kind of of fruits. An apple is also a fruit, and a banana is also a fruit. So, you have to make sure that you get all of them. Now, since generic types are invariant, in the sense, List<Apple>
is not the same as List<Fruit>
, you can't add a List<Apple>
if your type of list is List<List<Fruit>>
. For that you would need to use wildcards
like this - List<List<? extends Fruit>>
, which can now take List<Apple>
, List<Banana>
, list of any fruit.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With