Generics

Mixing generics with legacy code

    List<String> words = new ArrayList<String>();  
    words.add("house");  
    words.add("book");  
    addSth(words);  
      
    private void addSth(List list) {  
       list.add(new Integer(6));  
    }  
  • the above code compiles (but with warnings) and can work fine, at least to the place of addition (if the object was later retrieved from the List it could break down, e.g. words would be treated as List<String> but Integer objects was retrieved) – this code is unsafe
  • generic code is only for the compiler purposes; JVM knows nothing about what really the List holds
  • at runtime both legacy and Java 5 code (with generics) look the same, like pre-generic version
List<String> words = new ArrayList<String>();  

System.out.println(words instanceof List<String>);   // WON'T COMPILE

The above code won’t compile since all instances of a generic class have the same runtime class, regardless of their actual type parameters.

Instead, you should do as below:

    List<String> words = new ArrayList<String>();  
    System.out.println(words instanceof List);   // OK  

This is also worth a look:

Collection<String> words = new ArrayList<String>();  
List<Integer> numbers = new ArrayList<Integer>();  
System.out.println(words.getClass() == numbers.getClass()); // produces "true"

Polymorphism and generic methods

    class Superclass {}  
    class Subclass extends Superclass {}  
    ...  
    List<Superclass> oList = new ArrayList<Subclass>(); // WON'T COMPILE  
    Superclass [] oArray = new Subclass [5];            // OK  

It’s the same with methods:

    private void addSth(List<Superclass> list) {}  

The above method only accepts List<Superclass>, there’s no way it acceppts List<Subclass>

The solution:

    private void addSth(List<? extends Superclass> list) {}  
  • it accepts a List holding objects of Superclass type or any of its subtypes (abstract or concrete class) or objects that implement Superclass (in case it’s an interface)
  • can’t add anything to the list
    private void addSth(List<? super Subclass> list) {}  
  • it accepts a List holding objects of Subclass type or any other that are of type extended by Subclass
  • now the list can be modified (elements can be added)
    private void addSth(List<?> list) {}                      // 1  
    private void addSth(List<? extends Object> list) {} // 2  
    private void addSth(List<Object> list) {}               // 3  
  • 1 is the same as 2:
    • any type of List can be assigned to the argument
    • nothing can be added to the List
  • 3:
    • the method accepts only List<Objects>
    • objects can be added to the List

Wildcard notation (?) cannot be used after new when a new object is created:

    List<?> oList = new List<? extends Superclass>();  // WON'T COMPILE  

How to create a generic class and methods?

It’s worth to look at the following examples:

Example 1

public class MyGenericClass <T> {  
    private T instance;  
    public T [] oArray;  
  
    public MyGenericClass(T instance_p) {  
        instance = instance_p;  
    }  
  
    public T getInstance() {  
        return instance;  
    }  
  
    public void setInstance(T instance_p) {  
        instance = instance_p;  
    }  
}

Example 2

public class MyGenericClass2 {  
    public <T> void doSth(T instance_p) {  
        System.out.println("I'm doing sth...");  
    }  
}

Example 3

public class MyGenericClass3 <T, W> {  
    private T instance;  
    public W instance2;  
}
  • T (stands for “type”) can be exchanged with any valid identifier (e.g. E)
  • this identifier must be used instead of ? (which was described earlier)
  • a generic method can be defined with the type not defined in the class (look at 2nd example above): public void doSth(T instance_p) {}
Previous Post
Next Post