Generics Flashcards
Diamond Notation
Instead of HashMap<Integer, ArrayList<String>> mySet = new HashMap<Integer, ArrayList<String>>(); Java allows this HashMap<Integer, ArrayList<String>> mySet = new HashMap<>(); to avoid too much of typing Here, the generic parameters are omitted from the right side (leaving the angle brackets to form a diamond shape, thus the term diamond notation)</String></String></String>
Problem of Subtypes
Assume that you have a small inheritance hierarchy. To model people in a university, you have classes Student and Faculty and a common superclass Person. Now you also create types for lists of each of these: List<Student>, List<Faculty>, and List<Person> You have a method like private void printList(List<Person> list). Can you pass List<Faculty> to the method? Java does not allow that because you may pass List<Student> to the method and try to stuff a Faculty object into the List<Student> A solution is to declare that List<Student> is not a subtype of List<Person> However ArrayList<Person> is indeed a subtype of List<Person> as we dont have such issues</Person></Person></Person></Student></Student></Student></Faculty></Person></Person></Faculty></Student>
Type Erasure
At the core of type erasure is the fact that type parameters exist only at compile time; they are completely removed at runtime. it’s often helpful to think of generic classes as expanded at instantiation time class List<T> { public void add(T elem); ... } If it is then instantiated by using the concrete type List<String>, it can be thought of as having every occurrence of T in the source text replaced by String, so that the parameter type in the add method becomes String. For List<Integer>, each T would be replaced by Integer, and so on. This is a useful mental model to start understanding generics…but it is inaccurate. List<String>, List<Integer>, and List<Person> are all represented by a single class, List<object>, by the time your program executes Discarding type parameter information at runtime has advantages and disadvantages. One of the advantages is that it saves time and space: The class file needs to exist only once for every generic class.</object></Person></Integer></String></Integer></String></T>
Bounded Wild Card
private void printList(List<? extends Person> list) – allows List<subtypes> private void printList(List<? super Person> list) -- By using the super keyword for the declaration, I am stating that the type has to be Person or a supertype of Person.</subtypes>
Type Erasure and instanceOf
if (list instanceof List<Person>) { List<Person> pl = (List<Person>) list; } The runtime system has no idea whether a type is List<Person> because it does not keep this information around. (All the runtime knows about is List<object> but nothing more specific.) Therefore, the runtime cannot perform a type-safe check and give you an answer. You will see an error saying illegal generic type for instanceof.</object></Person></Person></Person></Person>
Type Erasusure and ==
List<Student> sl = new ArrayList<Student>(); List<Faculty> fl = new ArrayList<Faculty>(); if (sl.getClass() == fl.getClass()) ... The statement will evaluate to true. As far as the runtime system is concerned, the class of both objects is ArrayList.</Faculty></Faculty></Student></Student>
Generic Class
class Box<T> { private T contents; public Box(T contents) { this.contents = contents; } public void printDataType() { System.out.println("Type: " + this.contents.getClass().getSimpleName()); } } Box<Integer> integerBox = new Box<>(42);</Integer></T>
Generic Interface
interface Pair<K, V> { K getKey(); V getValue(); } class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) { this.key = key; this.value = value; } public K getKey() { return key; } public V getValue() { return value; } }
Generic Methods
<T1, T2, …, Tn> returnType methodName(parameters) { // block of code } public static <T, N> T methodName(T obj, N num) { // block of code }