
public void add(E element) public E get(int index)
ArrayList<BankAccount> ArrayList<Measurable>
ArrayList<double> // Wrong!
ArrayList<Double>
public void add(BankAccount element)
public void add(Object element)
ArrayList<BankAccount> accounts1 = new ArrayList<BankAccount>();
LinkedList accounts2 = new LinkedList(); // Should hold BankAccount objects
accounts1.add("my savings"); // Compile-time error
accounts2.add("my savings"); // Not detected at compile time
. . .
BankAccount account = (BankAccount) accounts2.getFirst(); // Run-time error
ArrayList<Integer> a = new ArrayList<>(); String s = a.get(0);
ArrayList<Double> a = new ArrayList<>(); a.add(3);
LinkedList a = new LinkedList();
a.addFirst("3.14");
double x = (Double) a.removeFirst();
Pair<String, Integer> result
= new Pair<>("Harry Hacker", 1729);
String name = result.getFirst(); Integer number = result.getSecond();
public class Pair<T, S>
| Type Variable | Meaning |
| E | Element type in a collection |
| K | Key type in a map |
| V | Value type in a map |
| T | General type |
| S, U | Additional general types |
public class Pair<T, S>public class Pair<T, S> { private T first; private S second; public Pair(T firstElement, S secondElement) { first = firstElement; second = secondElement; } public T getFirst() { return first; } public S getSecond() { return second; } }

Diana Expected: Diana 1 Expected: 1
public static Pair<Double, Double> roots(Double x)
{
if (x >= 0)
{
double r = Math.sqrt(x);
return new Pair<Double, Double>(r, -r);
}
else { return null; }
}
public class ArrayUtil
{
/**
Prints all elements in an array.
@param a the array to print
*/
public <T> static void print(T[] a)
{
. . .
}
. . .
}
public class ArrayUtil
{
public static void print(String[] a)
{
for (String e : a)
{
System.out.print(e + " ");
}
System.out.println();
}
. . .
}
public static <E> void print(E[] a) { for (E e : a) { System.out.print(e + " "); } System.out.println(); }
Rectangle[] rectangles = . . .; ArrayUtil.print(rectangles);

public static <T> void fill(List<T> lst, T value)
{
for (int i = 0; i < lst.size(); i++) { lst.set(i, value); }
}
If you have an array list
ArrayList
<String>
a = new ArrayList<String>(10);
how do you fill it with ten "*"?
public static <T> fill(T[] arr, T value)
{
for (int i = 0; i < arr.length; i++) { arr[i] = value; }
}
What happens when you execute the following statements?
String[] a = new String[10]; fill(a, 42);

You can place restrictions on the type parameters of generic classes and methods.
public interface Measurable
{
double getMeasure();
}public static <E extends Measurable> double average(ArrayList<E> objects)public static <E extends Measurable> double average(ArrayList<E> objects)
{
if (objects.size() == 0) { return 0; }
double sum = 0;
for (E obj : objects)
{
sum = sum + obj.getMeasure();
}
return sum / objects.size();
}
public interface Comparable<T>
{
int compareTo(T other);
}public static <E extends Comparable<E>> E min(ArrayList<E> objects)
{
E smallest = objects.get(0);
for (int i = 1; i < objects.size(); i++)
{
E obj = objects.get(i);
if (obj.compareTo(smallest) < 0)
{
smallest = obj;
}
}
return smallest;
}
int compareTo(E other)
obj.compareTo(smallest)
<E extends Comparable<E> & Cloneable>
extends or implements.
public class BinarySearchTree<E extends Comparable<E>>
or, if you read Special Topic 18.1,
public class BinarySearchTree<E extends Comparable<? super E>>
public static <E extends Measurable> E min(ArrayList<E> objects)
{
E smallest = objects.get(0);
for (int i = 1; i < objects.size(); i++)
{
E obj = objects.get(i);
if (obj.getMeasure() < smallest.getMeasure())
{
smallest = obj;
}
}
return smallest;
}
public static Measurable min(ArrayList<Measurable> a)
public static Measurable min(Measurable[] a)
public static <E extends Measurable> double average(E[] objects)
{
if (objects.length == 0) { return 0; }
double sum = 0;
for (E obj : objects)
{
sum = sum + obj.getMeasure();
}
return sum / objects.length;
}public static double average(Measurable[] objects)
{
if (objects.length == 0) { return 0; }
double sum = 0;
for (Measurable obj : objects)
{
sum = sum + obj.getMeasure();
}
return sum / objects.length;
}
For example, if BankAccount implements
Measurable, a BankAccount[] array is convertible
to a Measurable[] array. Contrast with Self
Check 19, where the return type was a generic
type. Here, the return type is double, and there
is no need for using generic types.ArrayList<SavingsAccount> savingsAccounts = new ArrayList<SavingsAccount>();
ArrayList<BankAccount> bankAccounts = savingsAccounts;
// Not legal - compile-time error
SavingsAccount[] savingsAccounts = new SavingsAccount[10];
BankAccount bankAccounts = savingsAccounts; // LegalBankAccount harrysChecking = new CheckingAccount();
bankAccounts[0] = harrysChecking; // Throws ArrayStoreException| Name | Syntax | Meaning |
|---|---|---|
| Wildcard with lower bound | ? extends B | Any subtype of B |
| Wildcard with upper bound | ? super B | Any supertype of B |
| Unbounded wildcard | ? | Any type |
public void addAll(LinkedList<? extends E> other)
{
ListIterator<E> iter = other.listIterator();
while (iter.hasNext())
{
add(iter.next());
}
}
public static <E extends Comparable<E>> E min(E[] a)
public static <E extends Comparable<? super E>> E min(E[] a)
static void reverse(List<?> list)
static void <T> reverse(List<T> list)

In the Java virtual machine, generic types are erased.
public class Pair
{
private Object first;
private Object second;
public Pair(Object firstElement, Object secondElement)
{
first = firstElement;
second = secondElement;
}
public Object getFirst() { return first; }
public Object getSecond() { return second; }
}
public static <E extends Measurable> E min(E[] objects)
{
E smallest = objects[0];
for (int i = 1; i < objects.length; i++)
{
E obj = objects[i];
if (obj.getMeasure() < smallest.getMeasure())
{
smallest = obj;
}
}
return smallest;
}
public static Measurable min(Measurable[] objects)
{
Measurable smallest = objects[0];
for (int i = 1; i < objects.length; i++)
{
Measurable obj = objects[i];
if (obj.getMeasure() < smallest.getMeasure())
{
smallest = obj;
}
}
return smallest;
}public static <E> void fillWithDefaults(E[] a)
{
for (int i = 0; i < a.length; i++)
a[i] = new E(); // ERROR
}
public static void fillWithDefaults(Object[] a) { for (int i = 0; i < a.length; i++) a[i] = new Object(); // Not useful }
public static <E> void fillWithDefaults(E[] a, E defaultValue)
{
for (int i = 0; i < a.length; i++)
a[i] = defaultValue;
}
public class Stack<E>
{
private E[] elements;
. . .
public Stack()
{
elements = new E[MAX_SIZE]; // Error
}
}
public class Stack<E>
{
private ArrayList<E> elements;
. . .
public Stack()
{
elements = new ArrayList<E>(); // Ok
}
. . .
}
public class Stack<E>
{
private Object[] elements;
private int currentSize;
. . .
public Stack()
{
elements = new Object[MAX_SIZE]; // Ok
}
. . .
public E pop()
{
size--;
return (E) elements[currentSize];
}
}public static <E> Comparable<E> min(Comparable<E>[] objects)
is an error. You cannot have an array of a
generic type.public static void print(Object[] a)
{
for (Object e : a)
{
System.out.print(e + " ");
}
System.out.println();
}public class Stack<E>
{
private E[] elements;
. . .
public Stack()
{
elements = (E[]) new Object[MAX_SIZE];
}
. . .
}
Object[] toArray()Why doesn't the method return an E[]?
E[] toArray(E[] a)Why can this method return an array of type E[]? (Hint: Special Topic 18.2.)
static <T> T[] copyOf(T[] original, int newLength)be implemented without reflection?