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>
  }
  
}