Wildcard (Java): Difference between revisions

Content deleted Content added
Fix formatting issues.
Example: Lists: Remove final keyword for function parameters
 
(3 intermediate revisions by the same user not shown)
Line 4:
== 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>.{{sfn|Bloch|2018|loc=Chapter §5 Item 26: Don't use raw types|pp=117-122}}
 
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 a supertype of all parameterizarions of the generic type <code>Generic</code>.{{sfn|Bloch|2018|loc=Chapter §5 Item 31: Use bounded wildcards to increase API flexibility|pp=139-145}} 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 3126: Use bounded wildcards toDon't increaseuse APIraw flexibilitytypes|pp=139117-145122}} 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 ==
Line 12:
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. However, objects of the unknown type can be read from the generic object and assigned to a variable of a supertype of the upperbound.
 
Sample code for the <code>Generic<T '''extends''' UpperBound></code> class:
<syntaxhighlight lang="java">
class Generic <T extends UpperBound> {
Line 22 ⟶ 23:
}
}
</syntaxhighlight>
 
Sample code that uses the <code>Generic<T '''extends''' UpperBound></code> class:
<syntaxhighlight lang="java">
...
final Generic<UpperBound> concreteTypeReference = 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
concreteTypeReference.write(new UpperBound()); // OK
...
</syntaxhighlight>
 
Line 62 ⟶ 68:
 
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>
<syntaxhighlight lang="java">
public void doSomething(List<? extends MyClass> list) {
for (final MyClass object : list) { // OK
// do something
}
Line 74 ⟶ 80:
<syntaxhighlight lang="java">
public void doSomething(List<? extends MyClass> list) {
final MyClass m = new MyClass();
list.add(m); // Compile error
}
</syntaxhighlight>
 
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>:
<syntaxhighlight lang="java">
public void doSomething(List<? super MyClass> list) {
final MyClass m = new MyClass();
list.add(m); // OK
}
Line 90 ⟶ 96:
<syntaxhighlight lang="java">
public void doSomething(List<? super MyClass> list) {
for (final MyClass object : list) { // Compile error
// do something
}
Line 96 ⟶ 102:
</syntaxhighlight>
 
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}}