Below is the code,
import java.util.List;
import java.util.ArrayList;
public class Dummy {
public static void main(String[] args) {
List
Here is some non-generic code:
public class MyList {
List myData = new ArrayList();
public void add(Object ob) {
myData.add(ob);
}
public Object getAtIndex(int ix) {
return myData.get(ix);
}
}
This code will allow you to store an object of any type into your MyList instances even if the contract of MyList specifies that the objects must all be of the same type. Moreover if you use a MyList instance to store String instances, you must manually cast them to String when you retrieve them.
String myString = (String) myList.get(1);
The above MyList class is not type safe. It is most definitely possible that the above assignment statement will fail with a ClassCastException if an object other than a String instance was stored into your MyList instance (which can happen at run-time without any complaint).
Here is a generified MyList class:
public class MyList<T> {
List<T> myData = new ArrayList<>();
public void add(T ob) {
myData.add(ob);
}
public T getAtIndex(int ix) {
return myData.get(ix);
}
}
Now, the compiler guarantees that only T
instances can be added and retrieved from MyList instances. Because the compiler guarantees that T
instances will always be returned, you can use syntax like this without any manual casting:
String myString = myList.get(1);
The generified MyList class is now type-safe. The compiler won't allow you to store anything but T
instances into your MyList instances, which guarantees that no ClassCastExceptions will occur at run-time. If you examine the byte-code, you'll find that the compiler has placed a cast automatically.
Generics in Java are a compile-time only phenomenon. In the byte-code, all references to T
in the MyList class above are replaced by Object
. This process is referred to as "type erasure". It is important to remember that type safety in Java is provided by the compiler only. If your program compiles without any errors AND without any warnings, then your program, generics and all, is type safe. The compiled program, however, has retained almost no information about the generic parameters.
From farther down in the class:
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
That @SuppressWarnings
tells the compiler that you're sure about the unchecked cast that you're performing there. Since all of the other operations, such as get(int)
, use the type parameter E
, this restricts the unsafe type handling to specific locations where the implementer can make sure to handle the cast correctly.