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
, DoubleConsumer
instanceof
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);
@SafeVarargs
public 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 ArrayList
public 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 Throwable
public 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> // Error
public 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 Manager
public 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 ChronoLocalDate
ChronoLocalDate
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:
T
java.lang.reflect.Type
interface has subinterfaces to analyze generic types at runtime.