import java.util.*; /* interface Comparable<T> { int compareTo( T o ); } interface Comparator<T> { int compare( T a, T b ); } */ class G21 { // almost java.util.Collections public static <E extends Comparable<? super E>> E max( Collection<E> c ){ // public static <E extends Comparable<? super E>> E max( Collection<? extends E> c ){ // almost good... return null; } static class Person { final String name; Person( String name ){ this.name = name; } } static class Driver extends Person { Driver( String name ){ super(name); } } static class PersonComparator implements Comparator<Person> { public int compare( Person a, Person b ){ return a.name.compareTo(b.name); } } public static <T> T max_1( Collection<T> c, Comparator<T> comp ){ return null; } public static <T> T max_2( Collection<? extends T> c, Comparator<T> comp ){ return null; } public static <T> T max_3( Collection<T> c, Comparator<? super T> comp ){ return null; } public static <T> T max( Collection<? extends T> c, Comparator<? super T> comp ){ return null; } public static void main( String[] args ){ PersonComparator pc = new PersonComparator(); List<Person> lp = new ArrayList<Person>(); Person p = max_1(lp, pc); List<Driver> ld = new ArrayList<Driver>(); p = max_2(ld, pc); Driver d = max_3(ld, new PersonComparator()); p = max_3(ld, pc); List<? extends Driver> lu = new ArrayList<Driver>(); d = max(lu, pc); d = max_3(lu, pc); } public static <T> void copy( List<? super T> dest, List<? extends T> src ){ for( T t: src ){ // t must be of type S where T <: S dest.add(t); // t must be of type S where S <: T (e.g. cannot add an object of a supertype) } // from here just trash for( Object o: dest ){ // cannot assume more on the elements of dest System.out.println(o); } // src.add( ... ); // cannot add anything to src, the type of the object that can be added is unknown List<?> list = dest; // it's like List<? extends Object> } }