Generics
- Type parameters are used to declare the return type, parameter types and local variable types
- When the compiler translates generic method into bytecodes, it removes the ytpe parameter section and replaces the type parameters with actual types
- By default all generic types are replaced with type Object
- A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety
- Restrictions
- Cannot Instantiate Generic Types with Primitive Types
- Cannot Create Instances of Type Parameters
- Cannot Declare Static Fields Whose Types are Type Parameters
- Cannot Use Casts or instanceof With Parameterized Types
- Cannot Create Arrays of Parameterized Types
- Cannot Create, Catch, or Throw Objects of Parameterized Types
- Cannot Overload a Method Where the Formal Parameter Types of Each Overload Erase to the Same Raw Type
Type Parameter Naming Conventions
- E - Element (used extensively by the Java Collections Framework)
- K - Key
- N - Number
- T - Type
- V - Value
- S,U,V etc. - 2nd, 3rd, 4th types
Type Casting
- Object o = new A()
- ((A)o).functionDefinedInA()
public class Box
{
private Object obj;
public Box(Object o)
{
obj = o;
}
public Object getObj()
{
return obj;
}
}
public class G
{
public static void main(String args[])
{
Box b = new Box("Hello World!");
String a = (String)b.getObj();//type casting
System.out.println(a.toLowerCase());
}
}
Generic Class
public class Box<T>
{
private T obj;
public Box(T o)
{
obj = o;
}
public T getObj()
{
return obj;
}
}
public class G
{
public static void main(String args[])
{
Box<String> b = new Box<String>("Hello World!");
String a = b.getObj();
System.out.println(a.toLowerCase());
}
}
Diamond
public class G
{
public static void main(String args[])
{
Box<String> b = new Box<>("Hello World!");
String a = b.getObj();
System.out.println(a.toLowerCase());
}
}
Multiple Types
public class Pair<T, S>
{
private T name;
private S age;
public Pair(T n, S a)
{
name = n;
age = a;
}
public T getName()
{
return name;
}
public S getAge()
{
return age;
}
}
public class G
{
public static void main(String args[])
{
Pair<String, Integer> p = new Pair<String, Integer>("Lin", 37);
System.out.println(p.getName()+": "+p.getAge());
}
}
Generic Method
public class G
{
public static <T, S> boolean compare(Pair<T, S> p1, Pair<T, S> p2)
{
if(p1.getName().equals(p2.getName()) && p1.getAge().equals(p2.getAge()))
return true;
else
return false;
}
public static void main(String args[])
{
Pair<String, Integer> p = new Pair<String, Integer>("Lin", 37);
Pair<String, Integer> p2 = new Pair<String, Integer>("Lin", 38);
Systemystem.out.println(G.<String, Integer>compare(p, p2));
System.out.println(compare(p, p2));//type interface
}
}
Bounded Type Parameters
- Restrict the types that can be used as type arguments in a parameterized type
public class Box<T extends Number>
{
private T obj;
public Box(T o)
{
obj = o;
}
public T getObj()
{
return obj;
}
}
public class G
{
public static void main(String args[])
{
Box<Integer> b = new Box<Integer>(100);
//Box<String> b = new Box<String>("Hello World!");//compile erro
System.out.println(b.getObj());
}
}
Wildcard
- Use ? 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)
- The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype
- The term List is more restrictive than List<? extends Number> because the former matches a list of type Number only, whereas the latter matches a list of type Number or any of its subclasses
import java.util.*;
public class G
{
public static double sumOfList(List<? extends Number> list) {
double s = 0.0;
for (Number n : list)
s += n.doubleValue();
return s;
}
public static void main(String args[])
{
List<Integer> li = Arrays.asList(1, 2, 3);
System.out.println("sum = " + sumOfList(li));
}
}
Generic Array
import java.util.*;
public class temp
{
public static void main(String args[])
{
List[] l2 = new List<?>[2];
l2[0] = new ArrayList<Integer>();
l2[1] = new ArrayList<Integer>();
l2[0].add(1);
l2[0].add(2);
Object [] array = l2[0].toArray();
for(Object e : array)
System.out.println(e);
}
}
Reference