Generics Flashcards
they add stability to your code by making more of your bugs detectable at compile time
generics
They provide a way for you to re-use the same code with different inputs
type parameters
Why use generics?
- stronger type checks at compile time
- elimination of casts
- enable programmers to implement generic algorithms
This is a generic class or interface that is parameterized over types
class name<T1, T2, …, Tn> { /* … */ }
generic type
You can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments (<>) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <>, is informally called the diamond.
Box<Integer> integerBox = new Box<>();</Integer>
The Diamond.
The name of a generic class or interface without any type arguments.
Raw Types
These are methods that introduce their own type parameters.
a type parameter before the return type of the
method declaration. This is needed even if the method is returning void.
Generic methods
methods are used to restrict the number of types of data for a class
Bounded Type
Parameters
a Java compiler’s ability to look at each method
invocation and corresponding declaration to determine the type
argument (or arguments) that make the invocation applicable.
Type inference
determines the types of the arguments and, if
available, the type that the result is being assigned, or returned.
tries to find the most specific type that
works with all of the arguments.
The inference algorithm
represents
an unknown type.
Wildcards ?
never used as a type argument for a generic method
invocation, a generic class instance creation, or a supertype.
wildcard
relax the restrictions on a variable.
restricts to its
sub-type.
Upper Bounded Wildcards.
List<? extends Number>
a list of unknown
type.
public static void printList(List<?> list) {
Unbounded Wildcards
<? super A>.
restricts the unknown type to be a specific type or a super-type
Lower Bounded Wildcards.
What does type erasure do?
- replace all type parameters in generic types with their bounds or object if the type parameters are unbounded.
- insert type casts if necessary to preserve type safety
- generate bridge methods to preserve polymorphism in extended generic types
It ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.
Type Erasure
Write a generic method to count the number of elements in a collection that have a specific property (for example, odd integers, prime numbers, palindromes).
public final class Algorithm {
public static <T> int countIf(Collection<T> c, UnaryPredicate<T> p) {</T></T></T>
int count = 0; for (T elem : c) if (p.test(elem)) \++count; return count; } }
Will the following class compile? If not, why?
public final class Algorithm {
public static <T> T max(T x, T y) {
return x > y ? x : y;
}
}</T>
No. The greater than (>) operator applies only to primitive numeric types.
Write a generic method to exchange the positions of two different elements in an array.
public final class Algorithm {
public static <T> void swap(T[] a, int i, int j) {
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}</T>
If the compiler erases all type parameters at compile time, why should you use generics?
You should use generics because:
The Java compiler enforces tighter type checks on generic code at compile time.
Generics support programming types as parameters.
Generics enable you to implement generic algorithms.
What is the following class converted to after type erasure?
public class Pair<K, V> {
public Pair(K key, V value) { this.key = key; this.value = value; } public K getKey(); { return key; } public V getValue(); { return value; } public void setKey(K key) { this.key = key; } public void setValue(V value) { this.value = value; } private K key; private V value; }
ublic class Pair {
public Pair(Object key, Object value) { this.key = key; this.value = value; } public Object getKey() { return key; } public Object getValue() { return value; } public void setKey(Object key) { this.key = key; } public void setValue(Object value) { this.value = value; } private Object key; private Object value; }
What is the following method converted to after type erasure?
public static <T extends Comparable<T>>
int findFirstGreaterThan(T[] at, T elem) {
// ...
}</T>
public static int findFirstGreaterThan(Comparable[] at, Comparable elem) {
// …
}
Will the following method compile? If not, why?
public static void print(List<? extends Number> list) {
for (Number n : list)
System.out.print(n + “ “);
System.out.println();
}
Yes
Write a generic method to find the maximal element in the range [begin, end) of a list.
import java.util.*;
public final class Algorithm {
public static <T extends Object & Comparable<? super T»
T max(List<? extends T> list, int begin, int end) {
T maxElem = list.get(begin); for (++begin; begin < end; ++begin) if (maxElem.compareTo(list.get(begin)) < 0) maxElem = list.get(begin); return maxElem; } }
Will the following class compile? If not, why?
public class Singleton<T> {</T>
public static T getInstance() { if (instance == null) instance = new Singleton<T>(); return instance; } private static T instance = null; }
No. You cannot create a static field of the type parameter T.
Given the following classes:
class Shape { /* … / }
class Circle extends Shape { / … / }
class Rectangle extends Shape { / … */ }
class Node<T> { /* ... */ }
Will the following code compile? If not, why?
Node<Circle> nc = new Node<>();
Node<Shape> ns = nc;</Shape></Circle></T>
No. Because Node<Circle> is not a subtype of Node<Shape>.</Shape></Circle>
Consider this class:
class Node<T> implements Comparable<T> {
public int compareTo(T obj) { /* ... */ }
// ...
}
Will the following code compile? If not, why?
Node<String> node = new Node<>();
Comparable<String> comp = node;</String></String></T></T>
Yes
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
Pair<int, char> p = new Pair<>(8, ‘a’);
Cannot Instantiate Generic Types with Primitive Types
public static <E> void append(List<E> list) {
E elem = new E(); // compile-time error
list.add(elem);
}</E></E>
Cannot Create Instances of Type Parameters
public static <E> void rtti(List<E> list) {
if (list instanceof ArrayList<Integer>) { // compile-time error
// ...
}</Integer></E></E>
Cannot Use Casts or instanceof with Parameterized Types
advantage of Generics in Java ?
Compile time safety
Type casting is not needed.
Type safety is ensured.
class Generic {
public static void main ( String args [ ] )
{
ArrayList<Integer> list = new ArrayList<Integer> ();</Integer></Integer>
list.add(100);
list.add(200);
list.add(300);
String a = list.get(2);
System.out.println(a);
}
}
300
class HashMap {
public static void main ( String args [ ] )
{
Map <Integer,String> map = new HashMap<Integer,String> ();
map.add(1,”one”);
map.add(2.”two”);
map.add(3.”three”);
Set<Map.Entry<Integer,String» set=map.entrySet();
Iterator<Map.Entry<Integer,String» itr=set.iterator();
while(itr.hasNext()){
Map.Entry e=itr.next();
System.out.println(e.getKey()+” “+e.getValue());
}
}
1 one 2 two 3 three
class Generic < G >
{
G obj;
Generic ( G obj )
{
this.obj = obj;
}
public G getObject ( ) {
return this.obj;
}
}
class Main {
public static void main ( String args [ ] )
{
Generic < Integer> obj1 = new Generic <Integer> (10);</Integer>
System.out.println(obj1.getObject());
Generic <String> obj2 = new Generic <String> (“DataFlair”);</String></String>
System.out.println(obj2.getObject());
}
}
10
Dataflair
class StringSample <S> {</S>
S obj;
StringSample( S obj )
{
this.obj = obj;
}
void print( ) {
return this.obj;
}
}
class Main {
public static void main ( String args [ ] )
{
Generic <Integer> object = new Generic <Integer> (“Ten”);</Integer></Integer>
System.out.println(object.print());
}
}
Ten
class Demo < O , T >
O = object1;
T = object2;
Demo ( object1 , object2 )
{
this.object1 = object1;
this.object2 = object2;
}
public void print ( object1 , object2 )
{
System.out.println( object1 + object2 );
}
}
class Main {
public static void main ( String args [ ] )
{
Demo < Integer , String > obj = new Demo < Integer , String > ( “Two” , 2 );
obj.print();
}
}
Parameters are changed and it raises an exception.
class GenericSample {
void method ( E element )
{
System.out.println(element.getclass().getName());
}
}
public static void main ( String args [ ] )
{
method(“DataFlair”);
}
}
java.lang.String
possible in Generic classes
Can pass two different parameters.
class Error {
Error( obj ) {
this.obj = obj;
}
void display( obj )
{
System.out.println(obj);
}
}
class Main {
public static void main ( String args [ ] )
{
Error < String > object = new Error < String > (“10”);
object.display();
}
}
No errors in the program 10 are displayed as output.
class DemoClass {
public <T> void genericsMethod(T data) {</T>
System.out.println(data); }
}
class Main {
public static void main(String args [ ] )
DemoClass demo = new DemoClass();
demo.<String>genericsMethod(“DataFlair”);</String>
}
}
DataFlair
used to display the package in generic classes
element.getClass();
class Arraylist {
public static void main ( String args [ ] )
{
ArrayList <> a = new ArrayList<> ();
a.add(“String”);
a.add(“Integer”);
a.add(2);
System.out.println(a.get(2));
}
Compilation error
class Sample < S , I >
S = obj1;
I = obj2;
Sample ( obj1 , obj2 )
{
this.obj1 = obj1;
this.obj2 = obj2;
}
public void text ( obj1 , obj2 )
{
System.out.println(obj1);
System.out.println(obj2);
}
}
class Main {
public static void main ( String args [ ] )
{
Sample < String , Integer > s = new Sample < String , Integer > ( “DataFlair” , 1 );
s.text();
}
}
Compilation error.