Understanding Java generics with the help of scenarios and working examples -- part 1
Q1. If java.lang.Object is the super type for java.lang.Number and, Number is the super type for java.lang.Integer, am I correct in saying that List<Object> is the super type for List<number> and, List<Number> is the super type for List<Integer>.
A1. No. List<Object> is not the the super type of List<Number>. If that were the case, then you could add objects of any type, and it defeats the purpose of Generics.
/* Compile Error: Type mismatch. Cannot convert from ArrayList<Integer> to List<Number>*/ List<Number> numbers2 = new ArrayList<Integer>(); //Compiles List<Integer> numbers3 = new ArrayList<Integer>(); /*Compile Error: Cannot instantiate the type ArrayList<? super Integer>*/ List<? super Integer> numbers6 = new ArrayList<? super Integer>(); //Compiles List<? super Integer> numbers7 = new ArrayList<Integer>(); numbers7.add(Integer.valueOf(5)); //ok //Compiles List<? extends Number> numbers5 = new ArrayList<Number>(); //Compile error: Read only.Can't add numbers5.add(Integer.valueOf(5));
In Generics, wildcards (i.e. ?), makes it possible to work with super classes and sub classes.
Q2. How will you go about deciding which of the following to use?
- <Number>
- <? extends Number>
- <? super Number>
A2. Here is the guide:
1. Use the ? extends wildcard if you need to retrieve object from a data structure. That is read only. You can't add elements to the collection.
2. Use the ? super wildcard if you need to put objects in a data structure.
3. If you need to do both things (read and add elements), don’t use any wildcard.
Let's take 3 scenarios to explain this.
Scenario 1: A custom generic class GenericSingleTypeScenario class that handles only Integer types.
import java.util.List; public class GenericSingleTypeScenario<Integer> { public void readOnly(List<? extends Number> numbers) { for (Number number : numbers) { System.out.println("readOnly: " + number); } } public void witeOnly(List<? super Integer> numbers, Integer aNumber) { numbers.add(aNumber); } public void witeAndRead(List<Integer> numbers, Integer aNumber) { numbers.add(aNumber); for (Integer integer : numbers) { System.out.println("readAndWrite: " + integer); } } }
Add a test class with a main method to test the above class
import java.util.ArrayList; import java.util.List; public class GenericSingleTypeScenarioTest { public static void main(String[] args) { GenericSingleTypeScenario<Integer> singleType = new GenericSingleTypeScenario<Integer>(); List<Integer> numbers = new ArrayList<Integer>(); numbers.add(1); //autoboxes 1 to type Integer singleType.readOnly(numbers); singleType.witeOnly(numbers, 6); //autoboxes 6 to type Integer singleType.witeAndRead(numbers, Integer.valueOf(9)); } }
Output:
readOnly: 1 readAndWrite: 1 readAndWrite: 6 readAndWrite: 9
Generics scenarios 2 and 3.
Labels: generics
0 Comments:
Post a Comment
Subscribe to Post Comments [Atom]
<< Home