Variables for the Compiler
The basic problem explained.
public void show()
{
List l = new ArrayList();
l.add("String");
l.add(new Integer(1));
l.add(new Random());
Object a = l.get(0);
Object b = l.get(1);
Object c = l.get(2);
// force type by casting
String s1 = (String) l.get(0);
Integer i1 = (Integer) l.get(1);
Random r1 = (Random) l.get(2);
// big mistake!!!
String s2 = (String) l.get(2);
Integer i2 = (Integer) l.get(0);
Random r2 = (Random) l.get(1);
}
ClassCastException
everywhere!
public void show()
{
List l = new ArrayList();
l.add("String");
l.add(new Integer(1));
l.add(new Random());
Object a = l.get(0);
Object b = l.get(1);
Object c = l.get(2);
// force type by casting
String s1 = (String) l.get(0);
Integer i1 = (Integer) l.get(1);
Random r1 = (Random) l.get(2);
// big mistake!!!
String s2 = (String) l.get(2);
Integer i2 = (Integer) l.get(0);
Random r2 = (Random) l.get(1);
}
public void show()
{
List<String> l = new ArrayList<String>();
l.add("String");
l.add(new Integer(1)); // compiler complains
l.add(new Random()); // compiler complains
Object a = l.get(0);
Object b = l.get(1);
Object c = l.get(2);
// force type by casting
String s1 = (String) l.get(0);
Integer i1 = (Integer) l.get(1); // compiler complains
Random r1 = (Random) l.get(2); // compiler complains
// only one way of usage possible now
String string1 = l.get(0);
String string2 = l.get(1);
}
public void show()
{
List<String> l = new ArrayList<String>();
l.add("String");
Object a = l.get(0);
Object b = l.get(1);
Object c = l.get(2);
// force type by casting
String s1 = (String) l.get(0);
// only one way of usage possible now
String string1 = l.get(0);
String string2 = l.get(1);
}
public void show()
{
List l = new ArrayList();
l.add("String");
Object a = l.get(0);
Object b = l.get(1);
Object c = l.get(2);
// force type by casting
String s1 = (String) l.get(0);
// only one way of usage possible now
String string1 = l.get(0);
String string2 = l.get(1);
}
Generics explained
List<T>
- generic type
T
- generic type
List<String>
- parameterized type
String
- actual type
List
- raw type
Really just a simple example
public class Box<T>
{
private T content;
public Box(T content)
{
this.content = content;
}
public T getContent()
{
return content;
}
}
public void show()
{
Box<String> box = new Box<String>("Foo");
String s = box.getContent();
}
Sure, that is a little simple...
Who wants to type?
<>
let's the compiler do the work
public void show()
{
Box<String> box = new Box<String>("Foo");
String s = box.getContent();
}
public void show()
{
Box<String> box = new Box<>("Foo"); // compile knows the rest
String s = box.getContent();
}
When generics hold other generics
public void show()
{
List<Map<Date, String>> listOfMaps = new ArrayList<Map<Date, String>>();
}
public void show()
{
List<Map<Date, String>> listOfMaps = new ArrayList<>();
}
When you don't have objects
public static <T> T eitherOr( T m, T n )
{
return Math.random() > 0.5 ? m : n;
}
When you don't know or care
public void show()
{
// raw-type usage warnings
List l = new ArrayList();
// you don't care, everything goes
List<?> m = new ArrayList<>();
}
Bound generics permit restrictions
super
T super Integer
/**
* Permits List<Integer>, List<Number>, List<Object>
*/
public void addNumbers(List<? super Integer> list)
extends
T extends Number
/**
* Permits List<Number>, List<Integer>, List<Float>
* List<Long>, List<Short> ...
*/
public void addNumbers(List<? extends Number> list)
Keep it simple!