Slide navigation: Forward with space bar, → arrow key, or PgDn. Backwards with ← or PgUp.

String and File objects.ArrayList class can collect instances of both classes.ArrayList used inheritance to be usable with multiple classes.
public class ArrayList // before type parameters
{
private Object[] elementData;
. . .
public Object get(int i) { . . . }
public void add(Object o) { . . . }
}
ArrayList files = new ArrayList();
. . .
String filename = (String) files.get(0);
files.add(new File(". . ."));
<...>, like this:
ArrayList<String> files = new ArrayList<>();
get method:
String filename = files.get(0);
add caught at compile time:
files.add(new File(". . .")); // Error
ArrayList are easy to use. ArrayList.
addAll to add an ArrayList<Manager> to an ArrayList<Employee>?Pair<T> Classpublic class Pair<T>
{
private T first;
private T second;
public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; }
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}
T in public class Pair<T> is a type variable.private T first;
Pair<String>, substituting a type for the variable.String getFirst() String getSecond() void setFirst(String) void setSecond(String)
public class Pair<T, U>
{
T first;
U second;
. . .
}
class ArrayAlg
{
public static <T> T getMiddle(T... a)
{
return a[a.length / 2];
}
}String middle = ArrayAlg.<String>getMiddle("John", "Q.", "Public");
String middle = ArrayAlg.getMiddle("John", "Q.", "Public");
double middle = ArrayAlg.getMiddle(3.14, 17.29, 0); // Type mismatch: cannot convert from Number&Comparable<?> to double
class ArrayAlg
{
public static <T> T min(T[] a) // almost correct
{
if (a == null || a.length == 0) return null;
T smallest = a[0];
for (int i = 1; i < a.length; i++)
if (smallest.compareTo(a[i]) > 0) smallest = a[i];
return smallest;
}
}
T has a compareTo method?T in the method declaration:
public static <T extends Comparable> T min(T[] a) ...
min can be called with arrays of String, LocalDate, and so on, but not Rectangle.Comparable also has a type parameter which we will ignore for a little longer.T extends Comparable & Cloneable
public class Pair
{
private Object first;
private Object second;
public Pair(Object first, Object second) { . . . }
public Object getFirst() { return first; }
public Object getSecond() { return second; }
public void setFirst(Object newValue) { first = newValue; }
public void setSecond(Object newValue) { second = newValue; }
}Object or first type bound:
public class Interval<T extends Comparable & Cloneable> // T turns into Comparable
Pair<Employee> buddies = . . .; Employee buddy = buddies.getFirst(); |
⇒ | Pair buddies = . . .; Employee buddy = (Employee) buddies.getFirst(); |
buddies.setFirst(buddy); // OK to convert Employee to Object
class DateInterval extends Pair<LocalDate>
{
public void setSecond(LocalDate second)
{
if (second.compareTo(getFirst()) >= 0)
super.setSecond(second);
}
. . .
}class DateInterval extends Pair
setSecond methods:
public void setSecond(LocalDate second) { . . . }
public void setSecond(Object second) { setSecond((LocalDate) second); }
Pair<LocalDate> pair = new DateInterval(); pair.setSecond(aDate);
class DateInterval extends Pair<LocalDate>
{
public LocalDate getSecond() { return (LocalDate) super.getSecond().clone(); }
. . .
}LocalDate getSecond() // defined in DateInterval Object getSecond() // overrides the method defined in Pair
Department with methods
ArrayList getEmployees() void addAll(ArrayList employees)
ArrayList<Employee> newHires = . . .; dept.addAll(newHires);
@SuppressWarnings("unchecked")@SuppressWarnings("unchecked") ArrayList<Employee> result = dept.getEmployees();
Object, they don't work for primitive types.java.util.function and java.util.stream have lots of baggage for primitive types.Consumer, IntConsumer, LongConsumer, DoubleConsumerinstanceof tests only work with raw types:
if (a instanceof Pair<String>) // Error
Pair<String> p = (Pair<String>) a; // Warning--can only test that a is a Pair
getClass method returns the raw type:
Pair<String> stringPair = . . .; Pair<Employee> employeePair = . . .; if (stringPair.getClass() == employeePair.getClass()) // they are equal
Pair<String>[] pairs = new Pair<String>[10]; // Error
Pair[] pairs = new Pair[10];
Object[] objects = pairs; objects[0] = "Fred"; // ArrayStoreException: Can't store a String into a Pair[]
objects[0] = new Pair<Integer>(...); // No ArrayStoreException
public static <T> void addAll(ArrayList<T> list, T... moreElements)
{
for (T element : moreElements) list.add(element);
}ArrayList<Pair<String>> stringPairs = . . .; Pair<String> pair1 = . . .; Pair<String> pair2 = . . .; addAll(stringPairs, pair1, pair2);
@SafeVarargspublic Pair() { first = new T(); second = new T(); } // Error
Pair<String> p = Pair.makePair(String::new);
public static <T> Pair<T> makePair(Supplier<T> constr)
{
return new Pair<>(constr.get(), constr.get());
}
public static <T> Pair<T> makePair(Class<T> cl) throws . . .
{
return new Pair<>(cl.newInstance(), cl.newInstance());
}
Pair<String> p = Pair.makePair(String.class);
new expression for arrays since the component type would be erased. public static <T extends Comparable> T[] minmax(T[] a)
{
T[] mm = new T[2]; // Error
. . .
}
public static Comparable[] minmax(Comparable[] a)
{
Comparable[] mm = new Comparable[2];
. . .
}
minmax with a String[] array, you would get a Comparable[] array back!Object[] array and casts:
public class ArrayList<E>
{
private Object[] elements;
. . .
@SuppressWarnings("unchecked") public E get(int n) { return (E) elements[n]; }
public void set(int n, E e) { elements[n] = e; } // no cast needed
}
toArray method of ArrayListpublic static <T extends Comparable> T[] minmax(T... a)
{
T[] mm = (T[]) Array.newInstance(a.getClass().getComponentType(), 2);
. . .
}
toArray methods:
Object[] toArray() T[] toArray(T[] result)
String[] ss = ArrayAlg.minmax(String[]::new, "Tom", "Dick", "Harry");
public static <T extends Comparable> T[] minmax(IntFunction<T[]> constr, T... a)
{
T[] mm = constr.apply(2);
. . .
}
public class Singleton<T>
{
private static T singleInstance; // Error
public static T getSingleInstance() // Error
{
if (singleInstance == null) construct new instance of T
return singleInstance;
}
}
Singleton<Random> and a Singleton<Logger>.Singleton class and only one static singleInstance field!public class Problem<T> extends Exception { /* . . . */ }
// Error--can't extend Throwablepublic static <T extends Throwable> void doWork(Class<T> t)
{
try { do work }
catch (T e) // Error--can't catch type variable
{ Logger.global.info("It didn't work"); }
}public static <T extends Throwable> void doWork() throws T // OK
{
try { do work }
catch (Throwable realCause)
{
t.initCause(realCause);
throw t;
}
}
public class Pair<T>
{
public boolean equals(T value) { return first.equals(value) && second.equals(value); }
. . .
}
boolean equals(Object value), which clashes with the equals method of the Object class!class Employee implements Comparable<Employee> { . . . }
class Manager extends Employee implements Comparable<Manager> // Errorpublic int compareTo(Object other) { return compareTo((Employee) other); }
public int compareTo(Object other) { return compareTo((Manager) other); }

SafeVarargs can be applied to private methods:
@SafeVarargs private <T> void process(T... values)
static and final methods and constructors.Manager is a subclass of Employee. Is Pair<Manager> a subclass of Pair<Employee>?GenericType<Type1> and GenericType<Type2>.

Pair<Manager> managerBuddies = new Pair<>(ceo, cfo); Pair<Employee> employeeBuddies = managerBuddies; // illegal, but suppose it wasn't employeeBuddies.setFirst(lowlyEmployee);
Manager[] managerBuddies = { ceo, cfo };
Employee[] employeeBuddies = managerBuddies; // OK
employeeBuddies[0] = lowlyEmployee; // ArrayStoreException

public class ArrayList<T> implements List<T>
ArrayList<Manager> bosses = . . .; ArrayList rawList = bosses;
rawList.set(0, new File(". . ."));
Pair<? extends Employee> pair;
Pair<Employee> or Pair<Manager>.public static void printBuddies(Pair<? extends Employee> pair)
{
Employee first = pair.getFirst();
Employee second = pair.getSecond();
System.out.println(first.getName() + " and " + second.getName() + " are buddies.");
}
? extends for ProducersPair<? extends Employee> pair produces data.Pair<? extends Employee> variable:
Pair<Manager> managerBuddies = new Pair<>(ceo, cfo); Pair<? extends Employee> wildcardBuddies = managerBuddies; // OK wildcardBuddies.setFirst(lowlyEmployee); // compile-time error
Pair<? extends Employee> methods look like this:
? extends Employee getFirst() void setFirst(? extends Employee)

? super Managerpublic static void minmaxBonus(Manager[] a, Pair<? super Manager> result)
{
. . .
result.setFirst(min);
result.setSecond(max);
}
Pair<? super Manager methods look like this:
? super Manager getFirst() void setFirst(? super Manager)
Comparable interface:
public interface Comparable<T>
{
public int compareTo(T other);
}
min:
public static <T extends Comparable<T>> T min(T[] a)
String which implements the Comparable<String> interface.LocalDate array!
LocalDate implements ChronoLocalDateChronoLocalDate extends Comparable<ChronoLocalDate>LocalDate does not implement Comparable<LocalDate>public static <T extends Comparable<? super T>> T min(T[] a) . . .
Pair<?> type?
? getFirst() void setFirst(?)
public static boolean hasNulls(Pair<?> p)
{
return p.getFirst() == null || p.getSecond() == null;
}public static <T> boolean hasNulls(Pair<T> p)
public static void swap(Pair<?> p)
? t = p.getFirst(); // Error p.setFirst(p.getSecond()); p.setSecond(t);
public static <T> void swapHelper(Pair<T> p)
{
T t = p.getFirst();
p.setFirst(p.getSecond());
p.setSecond(t);
}public static void swap(Pair<?> p) { swapHelper(p); }
? is, but it is a definite type that can be “captured” in the call <definite type>swapHelper.Class ClassClass is a generic type. String.class is an instance of Class<String>Class<T> has some methods with type parameters:
T newInstance() T cast(Object obj) T[] getEnumConstants() Class<? super T> getSuperclass() Constructor<T> getConstructor(Class<?>... parameterTypes) Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
public static <T> Pair<T> makePair(Class<T> cl) throws . . .
{
return new Pair<>(cl.newInstance(), cl.newInstance());
}
Pair<String> p = Pair.makePair(String.class);
Pair knows it came from generic Pair<T> class.public static <T extends Comparable<? super T>> T min(T[] a)
Method object of its erasure knows:
Tjava.lang.reflect.Type interface has subinterfaces to analyze generic types at runtime.