Wildcard (Java): Difference between revisions

Content deleted Content added
Example: Lists: Remove final keyword for function parameters
 
(32 intermediate revisions by 14 users not shown)
Line 1:
{{about|Java|the character|wildcard character}}
TheIn the [[Java (programming language)|Java programming language]], the '''wildcard''' <code>?</code> inis [[Javaa (programmingspecial language)kind of type argument<ref>{{Cite web|Java]]title=Chapter is4. aTypes, specialValues, [[typeand parameter]]Variables|url=https://docs.oracle.com/javase/specs/jls/se15/html/jls-4.html#jls-4.5.1|access-date=2020-11-03|website=docs.oracle.com}}</ref> that controls the [[type safety]] of the use of [[Generics in Java|generic]] (parameterized) types.{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} It can be used in variable declarations and instantiations<!--in special circumstances, see section below)--> as well as in method definitions, but not in the definition of a generic type.<ref name="gilad2004">{{citecitation|title=Generics in the Java Programming Language|url= http://www.oracle.com/technetwork/java/javase/generics-tutorial-159168.pdf|author=Gilad Bracha|date=June 2004|section=4. Wildcards|accessdate=6 March 2016}}</ref><ref>{{citecitation|url=http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.2|title=The Java Language Specification|section=8.1.2 Generic Classes and Type Parameters|publisher=Oracle|accessdate=6 March 2016}}</ref> This is a form of ''use-site'' [[variance annotation]], in contrast with the ''definition-site'' variance annotations found in [[C Sharp (programming language)|C#]] and [[Scala (programming language)|Scala]].
 
== Covariance for generic types ==
 
Unlike arrays (which are [[Covariance and contravariance (computer science)#Covariant arrays in Java and C#|covariant]] in Java{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}}), different instantiations of a generic type are not compatible with each other, not even explicitly.{{sfn|Bloch|2018|loc=Chapter §5 Item 26: WithDon't use raw types|pp=117-122}} For example, the declarationdeclarations <code>Generic<Supertype> superGeneric; Generic<Subtype> subGeneric;</code> will cause the compiler wouldto report a conversion errorerrors for both castings <code>(Generic<Subtype>)superGeneric</code> and <code>(Generic<Supertype>)subGeneric</code>.
 
This incompatibility maycan be softened by the wildcard if <code>?</code> is used as an actual type parameter.{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} <code>Generic<?></code> is the abstracta supertype forof all parameterizarions of the generic type <code>Generic</code>. This this allows objects of type <code>Generic<Supertype></code> and <code>Generic<Subtype></code> to be safely assigned to a variable or method parameter of type <code>Generic<?></code>.{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}} Using <code>Generic<? extends Supertype></code> allows the same, restricting compatibility to <code>Supertype</code> and its children.{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} Another possibility is <code>Generic<? super Subtype></code>, which also accepts both objects and restricts compatibility to <code>Subtype</code> and all its parents.{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}}
 
== Wildcard as parameter type ==
 
In the body of a generic unit, the (formal) type parameter is handled like its [[bounded quantification|upper bound]] (expressed with <code>'''extends'''</code>; <code>Object</code> if not constrained).{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} If the return type of a method is the type parameter, the result (e.g. of type <code>?</code>) can be referenced by a variable of the type of the upper bound (or <code>Object</code>). In the other direction, the wildcard fits no other type, not even <code>Object</code>: If <code>?</code> has been applied as the formal type parameter of a method, no actual parameters can be passed to it. ItHowever, objects of the unknown type can be calledread onlyfrom bythe castinggeneric theobject wildcardand reference:assigned to a variable of a supertype of the upperbound.
 
Sample code for the <code>Generic<T '''extends''' UpperBound></code> class:
<source lang="java5">
<syntaxhighlight lang="java">
class Generic <T extends UpperBound> {
private T t;
void write(T t) {
this.t = t;
}
}
T read() {
return t;
}
}
}
</syntaxhighlight>
 
Sample code that uses the <code>Generic<T '''extends''' UpperBound></code> class:
<syntaxhighlight lang="java">
...
final Generic<?UpperBound> wildcardReferenceconcreteTypeReference = new Generic<UpperBound>();
final Generic<?> wildcardReference = concreteTypeReference;
final UpperBound ub = wildcardReference.read(); // Object would also be OK
wildcardReference.write(new Object()); // type error
wildcardReference.write(new UpperBound()); // type error
((Generic<UpperBound>)wildcardReference)concreteTypeReference.write(new UpperBound()); // OK
...
</source>
</syntaxhighlight>
 
== Bounded Wildcardswildcards ==
 
A bounded wildcard is one with either an upper or a lower [[Inheritance (object-oriented programming)|inheritance]] constraint. The Notbound onlyof thea formalwildcard can be either a class type, parameters[[Interface in(Java)|interface]] thetype, genericarray unittype, butor type variable. Upper bounds are expressed alsousing the wildcard'''extends''' cankeyword beand (further)lower constrainedbounds ifusing onethe doesn't''super''' wantkeyword. toWildcards becan compatiblestate witheither allan instantiations:upper bound ''or'' a lower bound, but not both.
 
=== Upper bounds ===
An upper bound on a wildcard must be a subtype of the upper bound of the corresponding type parameter declared in the corresponding generic type.{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} An example of a wildcard that explicitly states an upper bound is:
 
<code>Generic<? '''extends''' SubtypeOfUpperBound> referenceConstrainedFromAbove;</code>
 
This reference can hold any instantiationparameterization of <code>Generic</code> withwhose antype actualargument typeis parametera subtype of <code>SubtypeOfUpperBound</code>'s subtype. A wildcard that does not haveexplicitly astate constraintan upper bound is effectively the same as one that has the constraint <code>extends Object</code>, since all reference types implicitlyin extendJava are subtypes of Object.

=== Lower bounds ===
A constraintwildcard with a lower bound, such as
 
<code>Generic<? '''super''' SubtypeOfUpperBound> referenceConstrainedFromBelow;</code>
 
can hold instantiationsany parameterization of <code>Generic</code> withwhose any supertypetype (e.g.argument <code>UpperBound</code>)is ofboth <code>SubtypeOfUpperBound</code>.a (Suchsubtype aof wildcardthe stillcorresponding hastype an implicitparameter's upper bound and a supertype of <code>ObjectSubtypeOfUpperBound</code>.){{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}}
 
== Object Creationcreation with Wildcardwildcard ==
It is even possible to constrain a reference's compatibility from both sides: from above by a generic class or method definition (<code><SubtypeOfUpperBound '''extends''' UpperBound></code>), or from below by the reference declaration (<code><? '''super''' SubtypeOfUpperBound></code>).
 
No objects may be created with a wildcard type parameterargument: for example, <code>'''new''' Generic<?>()</code> is forbidden because <code>Generic<?></code> is abstract. In practice, this is unnecessary because if one wanted to create an object that was assignable to a variable of type <code>Generic<?></code>, one could simply use any arbitrary type (that falls within the constraints of the wildcard, if any) as the type parameterargument.
== Object Creation with Wildcard ==
No objects may be created with a wildcard type parameter: <code>'''new''' Generic<?>()</code> is forbidden because <code>Generic<?></code> is abstract. In practice, this is unnecessary because if one wanted to create an object that was assignable to a variable of type <code>Generic<?></code>, one could simply use any arbitrary type (that falls within the constraints of the wildcard, if any) as the type parameter.
 
However, <code>new ListArrayList<Generic<?>>()</code> is allowed, because the wildcard is not a parameter to the instantiated type <code>ListArrayList</code>. The same holds for <code>new ListArrayList<List<?>>()</code>.
 
AnIn an array objectcreation thatexpression, isthe ancomponent arraytype of athe parameterized typearray maymust be createdreifiable onlyas defined by anthe unconstrainedJava (iLanguage Specification, Section 4.e7. withThis anentails unboundthat, wildcardif typethe parameter)component type asof the componentarray has any type: arguments, they must all be unbounded wildcards (wildcards consisting of only a <code>?</code>) . For example, <code>'''new''' Generic<?>[20]</code> is correct, while <code>'''new''' Generic<SomeType>[20]</code> is not.
 
For both cases, using no parameters is another option. This will generate a warning since it is less type-safe (see [[Raw type]]).
 
== Example: Lists ==
 
In the Java Collections Framework, the class <code>List<MyClass></code> represents an ordered collection of objects of type <code>MyClass</code>.
Upper bounds are specified using <code>'''extends'''</code>:
A <code>List<? '''extends''' MyClass></code> is a list of objects of some subclass of <code>MyClass</code>, i.e. any object in the list is guaranteed to be of type <code>MyClass</code>, so one can iterate over it using a variable of type <code>MyClass</code><ref>[[Inheritance (object-oriented programming)]]</ref>
<sourcesyntaxhighlight lang="java5java">
public void doSomething(List<? extends MyClass> list) {
for (final MyClass object : list) { // OK
// do something
}
}
</syntaxhighlight>
</source>
However, it is not guaranteed that one can add any object of type <code>MyClass</code> to that list:
<sourcesyntaxhighlight lang="java5java">
public void doSomething(List<? extends MyClass> list) {
final MyClass m = new MyClass();
list.add(m); // Compile error
}
</syntaxhighlight>
</source>
 
The converse is true for lower bounds, which are specified using <code>'''super'''</code>:
A <code>List<? '''super''' MyClass></code> is a list of objects of some superclass of <code>MyClass</code>, i.e. the list is guaranteed to be able to contain any object of type <code>MyClass</code>, so one can add any object of type <code>MyClass</code>:
<sourcesyntaxhighlight lang="java5java">
public void doSomething(List<? super MyClass> list) {
final MyClass m = new MyClass();
list.add(m); // OK
}
</syntaxhighlight>
</source>
However, it is not guaranteed that one can iterate over that list using a variable of type <code>MyClass</code>:
<sourcesyntaxhighlight lang="java5java">
public void doSomething(List<? super MyClass> list) {
for (final MyClass object : list) { // Compile error
// do something
}
}
</syntaxhighlight>
</source>
 
In order to be able to do both add objects of type <code>MyClass</code> to the list and iterate over it using a variable of type <code>MyClass</code>, a <code>List<MyClass></code> is needed, which is the only type of <code>List</code> that is both <code>List<? '''extends''' MyClass></code> and <code>List<? '''super''' MyClass></code>.<ref>[[Java syntax|Java syntax(Generics)]]</ref>
 
The mnemonics PECS (Producer Extends, Consumer Super) from the book '''Effective Java''' by [[Joshua Bloch]] gives an easy way to remember when to use wildcards (corresponding to Covariance and Contravariance) in Java.{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}}
 
==See also==
Line 95 ⟶ 111:
* [[Covariance and contravariance (computer science)]]
* [[Generics in Java#Type wildcards]] section explains lower and upper wildcard bounds
 
== Citations ==
{{Reflist}}
 
== References ==
*{{cite book | title= "Effective Java: Programming Language Guide" |last=Bloch| first=Joshua| publisher=[[Addison-Wesley]] | edition=third | isbn=978-0134685991| year=2018}}
* The Java Language Specification, Third Edition (Sun), {{ISBN |978-0-321-24678-3}} http://java.sun.com/docs/books/jls/
* Java Tutorials, Lesson Generics http://download.oracle.com/javase/tutorial/java/generics/index.html
* Capturing Wildcards, http://bayou.io/draft/Capturing_Wildcards.html
* Typkompatibilität in Java http://public.beuth-hochschule.de/~solymosi/veroeff/typkompatibilitaet/Typkompatibilitaet.html#Joker (in German)
 
 
{{DEFAULTSORT:Wildcard (Java)}}