Java基础之十五 泛型

  • 2019 年 10 月 3 日
  • 笔记

???? ??

???????????????????????????????????????????????????????????????????????
??????????????????????
???????????????????????????

15.2 ????

??????????????
??????????????

class Automobile {}    public class Holder1 {    private Automobile a;    public Holder1(Automobile a) { this.a = a; }    Automobile get() { return a; }  }

????Object?????,?????????????

public class Holder2 {    private Object a;    public Holder2(Object a) { this.a = a; }    public void set(Object a) { this.a = a; }    public Object get() { return a; }    public static void main(String[] args) {      Holder2 h2 = new Holder2(new Automobile());      Automobile a = (Automobile)h2.get();      h2.set("Not an Automobile");      String s = (String)h2.get();      h2.set(1); // Autoboxes to Integer      Integer x = (Integer)h2.get();    }  }

???????

public class Holder3<T> {    private T a;    public Holder3(T a) { this.a = a; }    public void set(T a) { this.a = a; }    public T get() { return a; }    public static void main(String[] args) {      Holder3<Automobile> h3 =        new Holder3<Automobile>(new Automobile());      Automobile a = h3.get(); // No cast needed      // h3.set("Not an Automobile"); // Error      // h3.set(1); // Error    }  }

15.2.1??????

???????????????????????????????????????????????????????
????????????????????????????

//: generics/TupleTest.java  import net.mindview.util.*;    class Amphibian {}  class Vehicle {}    public class TupleTest {    static TwoTuple<String,Integer> f() {      // Autoboxing converts the int to Integer:      return new TwoTuple<String,Integer>("hi", 47);    }    static ThreeTuple<Amphibian,String,Integer> g() {      return new ThreeTuple<Amphibian, String, Integer>(        new Amphibian(), "hi", 47);    }    static    FourTuple<Vehicle,Amphibian,String,Integer> h() {      return        new FourTuple<Vehicle,Amphibian,String,Integer>(          new Vehicle(), new Amphibian(), "hi", 47);    }    static    FiveTuple<Vehicle,Amphibian,String,Integer,Double> k() {      return new        FiveTuple<Vehicle,Amphibian,String,Integer,Double>(          new Vehicle(), new Amphibian(), "hi", 47, 11.1);    }    public static void main(String[] args) {      TwoTuple<String,Integer> ttsi = f();      System.out.println(ttsi);      // ttsi.first = "there"; // Compile error: final      System.out.println(g());      System.out.println(h());      System.out.println(k());    }  } /* Output: (80% match)  (hi, 47)  (Amphibian@1f6a7b9, hi, 47)  (Vehicle@35ce36, Amphibian@757aef, hi, 47)  (Vehicle@9cab16, Amphibian@1a46e30, hi, 47, 11.1)  *///:~

15.2.2 ?????

public class LinkedStack<T> {    private static class Node<U> {      U item;      Node<U> next;      Node() { item = null; next = null; }      Node(U item, Node<U> next) {        this.item = item;        this.next = next;      }      boolean end() { return item == null && next == null; }    }    private Node<T> top = new Node<T>(); // End sentinel    public void push(T item) {      top = new Node<T>(item, top);    }    public T pop() {      T result = top.item;      if(!top.end())        top = top.next;      return result;    }    public static void main(String[] args) {      LinkedStack<String> lss = new LinkedStack<String>();      for(String s : "Phasers on stun!".split(" "))        lss.push(s);      String s;      while((s = lss.pop()) != null)        System.out.println(s);    }  } /* Output:  stun!  on  Phasers  *///:~

15.2.3 RandomList

//: generics/RandomList.java  import java.util.*;    public class RandomList<T> {    private ArrayList<T> storage = new ArrayList<T>();    private Random rand = new Random(47);    public void add(T item) { storage.add(item); }    public T select() {      return storage.get(rand.nextInt(storage.size()));    }    public static void main(String[] args) {      RandomList<String> rs = new RandomList<String>();      for(String s: ("The quick brown fox jumped over " +          "the lazy brown dog").split(" "))        rs.add(s);      for(int i = 0; i < 11; i++)        System.out.print(rs.select() + " ");    }  } /* Output:  brown over fox quick quick dog brown The brown lazy brown  *///:~

15.3 ????

????????????????????????????????????????????????????????????????????????????????????

package coffee;  public class Americano extends Coffee {}  .  .  .  

??Generator< Coffee >??????????????

package coffee;  import java.util.*;  import net.mindview.util.*;    public class CoffeeGenerator  implements Generator<Coffee>, Iterable<Coffee> {    private Class[] types = { Latte.class, Mocha.class,      Cappuccino.class, Americano.class, Breve.class, };    private static Random rand = new Random(47);    public CoffeeGenerator() {}    // For iteration:    private int size = 0;    public CoffeeGenerator(int sz) { size = sz; }    public Coffee next() {      try {        return (Coffee)          types[rand.nextInt(types.length)].newInstance();        // Report programmer errors at run time:      } catch(Exception e) {        throw new RuntimeException(e);      }    }    class CoffeeIterator implements Iterator<Coffee> {      int count = size;      public boolean hasNext() { return count > 0; }      public Coffee next() {        count--;        return CoffeeGenerator.this.next();      }      public void remove() { // Not implemented        throw new UnsupportedOperationException();      }    }    public Iterator<Coffee> iterator() {      return new CoffeeIterator();    }    public static void main(String[] args) {      CoffeeGenerator gen = new CoffeeGenerator();      for(int i = 0; i < 5; i++)        System.out.println(gen.next());      for(Coffee c : new CoffeeGenerator(5))        System.out.println(c);    }  }

?????Fibonacci???

import net.mindview.util.*;    public class Fibonacci implements Generator<Integer> {    private int count = 0;    public Integer next() { return fib(count++); }    private int fib(int n) {      if(n < 2) return 1;      return fib(n-2) + fib(n-1);    }    public static void main(String[] args) {      Fibonacci gen = new Fibonacci();      for(int i = 0; i < 18; i++)        System.out.print(gen.next() + " ");    }  }

??????????????????????Java SE5????????????????
??????????

import java.util.*;    public class IterableFibonacci  extends Fibonacci implements Iterable<Integer> {    private int n;    public IterableFibonacci(int count) { n = count; }    public Iterator<Integer> iterator() {      return new Iterator<Integer>() {        public boolean hasNext() { return n > 0; }        public Integer next() {          n--;          return IterableFibonacci.this.next();        }        public void remove() { // Not implemented          throw new UnsupportedOperationException();        }      };    }    public static void main(String[] args) {      for(int i : new IterableFibonacci(18))        System.out.print(i + " ");    }  } 

15.4 ????

?????????????????????????????????????static????????????????????static???????????????????????
????????????????????????

public class GenericMethods {    public <T> void f(T x) {      System.out.println(x.getClass().getName());    }    public static void main(String[] args) {      GenericMethods gm = new GenericMethods();      gm.f("");      gm.f(1);      gm.f(1.0);      gm.f(1.0F);      gm.f('c');      gm.f(gm);    }  } /* Output:  java.lang.String  java.lang.Integer  java.lang.Double  java.lang.Float  java.lang.Character  GenericMethods  *///:~

?????????????????????????????????????????
???????????????????????????????????????????

15.4.1 ??????????

????????????????static??????????????

public class New  {      public static <K,V> Map<K,V> map(){          return new HashMap<K,V>();      }  }
import pets.*;  import java.util.*;  import net.mindview.util.*;    public class SimplerPets {    public static void main(String[] args) {      Map<Person, List<? extends Pet>> petPeople = New.map();      // Rest of the code is the same...    }  } ///:~

?????????????????????????????????????????????????????????????????????????????????????????Object??????

???????

????????????????????????????????????????

import pets.*;  import java.util.*;  import net.mindview.util.*;    public class ExplicitTypeSpecification {    static void f(Map<Person, List<Pet>> petPeople) {}    public static void main(String[] args) {      f(New.<Person, List<Pet>>map());    }  } ///:~

15.4.2 ?????????

???????????????????

import java.util.*;    public class GenericVarargs {    public static <T> List<T> makeList(T... args) {      List<T> result = new ArrayList<T>();      for(T item : args)        result.add(item);      return result;    }    public static void main(String[] args) {      List<String> ls = makeList("A");      System.out.println(ls);      ls = makeList("A", "B", "C");      System.out.println(ls);      ls = makeList("ABCDEFFHIJKLMNOPQRSTUVWXYZ".split(""));      System.out.println(ls);    }  } /* Output:  [A]  [A, B, C]  [, A, B, C, D, E, F, F, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]  *///:~

15.4.3 ??Generator?????

import coffee.*;  import java.util.*;  import net.mindview.util.*;    public class Generators {    public static <T> Collection<T>    fill(Collection<T> coll, Generator<T> gen, int n) {      for(int i = 0; i < n; i++)        coll.add(gen.next());      return coll;    }    public static void main(String[] args) {      Collection<Coffee> coffee = fill(        new ArrayList<Coffee>(), new CoffeeGenerator(), 4);      for(Coffee c : coffee)        System.out.println(c);      Collection<Integer> fnumbers = fill(        new ArrayList<Integer>(), new Fibonacci(), 12);      for(int i : fnumbers)        System.out.print(i + ", ");    }  } /* Output:  Americano 0  Latte 1  Americano 2  Mocha 3  1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144,  *///:~

15.4.4 ?????Generator

public class CountedObject {    private static long counter = 0;    private final long id = counter++;    public long id() { return id; }    public String toString() { return "CountedObject " + id;}  } ///:~
import net.mindview.util.*;    public class BasicGeneratorDemo {    public static void main(String[] args) {      Generator<CountedObject> gen =        BasicGenerator.create(CountedObject.class);      for(int i = 0; i < 5; i++)        System.out.println(gen.next());    }  } /* Output:  CountedObject 0  CountedObject 1  CountedObject 2  CountedObject 3  CountedObject 4  *///:~

15.4.5 ???????

//: generics/TupleTest2.java  import net.mindview.util.*;  import static net.mindview.util.Tuple.*;    public class TupleTest2 {    static TwoTuple<String,Integer> f() {      return tuple("hi", 47);    }    static TwoTuple f2() { return tuple("hi", 47); }    static ThreeTuple<Amphibian,String,Integer> g() {      return tuple(new Amphibian(), "hi", 47);    }    static    FourTuple<Vehicle,Amphibian,String,Integer> h() {      return tuple(new Vehicle(), new Amphibian(), "hi", 47);    }    static    FiveTuple<Vehicle,Amphibian,String,Integer,Double> k() {      return tuple(new Vehicle(), new Amphibian(),        "hi", 47, 11.1);    }    public static void main(String[] args) {      TwoTuple<String,Integer> ttsi = f();      System.out.println(ttsi);      System.out.println(f2());      System.out.println(g());      System.out.println(h());      System.out.println(k());    }  } /* Output: (80% match)  (hi, 47)  (hi, 47)  (Amphibian@7d772e, hi, 47)  (Vehicle@757aef, Amphibian@d9f9c3, hi, 47)  (Vehicle@1a46e30, Amphibian@3e25a5, hi, 47, 11.1)  *///:~

15.4.6 ??Set????

15.5 ?????

????????????????????????????Generator???

//: generics/BankTeller.java  // A very simple bank teller simulation.  import java.util.*;  import net.mindview.util.*;    class Customer {    private static long counter = 1;    private final long id = counter++;    private Customer() {}    public String toString() { return "Customer " + id; }    // A method to produce Generator objects:    public static Generator<Customer> generator() {      return new Generator<Customer>() {        public Customer next() { return new Customer(); }      };    }  }    class Teller {    private static long counter = 1;    private final long id = counter++;    private Teller() {}    public String toString() { return "Teller " + id; }    // A single Generator object:    public static Generator<Teller> generator =      new Generator<Teller>() {        public Teller next() { return new Teller(); }      };  }    public class BankTeller {    public static void serve(Teller t, Customer c) {      System.out.println(t + " serves " + c);    }    public static void main(String[] args) {      Random rand = new Random(47);      Queue<Customer> line = new LinkedList<Customer>();      Generators.fill(line, Customer.generator(), 15);      List<Teller> tellers = new ArrayList<Teller>();      Generators.fill(tellers, Teller.generator, 4);      for(Customer c : line)        serve(tellers.get(rand.nextInt(tellers.size())), c);    }  } /* Output:  Teller 3 serves Customer 1  Teller 2 serves Customer 2  Teller 3 serves Customer 3  Teller 1 serves Customer 4  Teller 1 serves Customer 5  Teller 3 serves Customer 6  Teller 1 serves Customer 7  Teller 2 serves Customer 8  Teller 3 serves Customer 9  Teller 3 serves Customer 10  Teller 2 serves Customer 11  Teller 4 serves Customer 12  Teller 2 serves Customer 13  Teller 1 serves Customer 14  Teller 1 serves Customer 15  *///:~

15.6 ??????

??????????????????????????
??List???

//: generics/TupleList.java  // Combining generic types to make complex generic types.  import java.util.*;  import net.mindview.util.*;    public class TupleList<A,B,C,D>  extends ArrayList<FourTuple<A,B,C,D>> {    public static void main(String[] args) {      TupleList<Vehicle, Amphibian, String, Integer> tl =        new TupleList<Vehicle, Amphibian, String, Integer>();      tl.add(TupleTest.h());      tl.add(TupleTest.h());      for(FourTuple<Vehicle,Amphibian,String,Integer> i: tl)        System.out.println(i);    }  } /* Output: (75% match)  (Vehicle@11b86e7, Amphibian@35ce36, hi, 47)  (Vehicle@757aef, Amphibian@d9f9c3, hi, 47)  *///:~

???????????????????

//: generics/Store.java  // Building up a complex model using generic containers.  import java.util.*;  import net.mindview.util.*;    //??  class Product {    private final int id;    private String description;    private double price;    public Product(int IDnumber, String descr, double price){      id = IDnumber;      description = descr;      this.price = price;      System.out.println(toString());    }    public String toString() {      return id + ": " + description + ", price: $" + price;    }    public void priceChange(double change) {      price += change;    }    public static Generator<Product> generator =      new Generator<Product>() {        private Random rand = new Random(47);        public Product next() {          return new Product(rand.nextInt(1000), "Test",            Math.round(rand.nextDouble() * 1000.0) + 0.99);        }      };  }    //??  class Shelf extends ArrayList<Product> {    public Shelf(int nProducts) {      Generators.fill(this, Product.generator, nProducts);    }  }    //??  class Aisle extends ArrayList<Shelf> {    public Aisle(int nShelves, int nProducts) {      for(int i = 0; i < nShelves; i++)        add(new Shelf(nProducts));    }  }    class CheckoutStand {}  class Office {}    //??  public class Store extends ArrayList<Aisle> {    private ArrayList<CheckoutStand> checkouts =      new ArrayList<CheckoutStand>();    private Office office = new Office();    public Store(int nAisles, int nShelves, int nProducts) {      for(int i = 0; i < nAisles; i++)        add(new Aisle(nShelves, nProducts));    }    public String toString() {      StringBuilder result = new StringBuilder();      for(Aisle a : this)        for(Shelf s : a)          for(Product p : s) {            result.append(p);            result.append("n");          }      return result.toString();    }    public static void main(String[] args) {      System.out.println(new Store(14, 5, 10));    }  } /* Output:  258: Test, price: $400.99  861: Test, price: $160.99  868: Test, price: $417.99  207: Test, price: $268.99  551: Test, price: $114.99  278: Test, price: $804.99  520: Test, price: $554.99  140: Test, price: $530.99  ...  *///:~

15.7 ???????

??????ArrayList.class??????ArrayList< Integer >.class

import java.util.*;    public class ErasedTypeEquivalence {    public static void main(String[] args) {      Class c1 = new ArrayList<String>().getClass();      Class c2 = new ArrayList<Integer>().getClass();      System.out.println(c1 == c2);    }  } /* Output:  true  *///:~
//: generics/LostInformation.java  import java.util.*;    class Frob {}  class Fnorkle {}  class Quark<Q> {}  class Particle<POSITION,MOMENTUM> {}    public class LostInformation {    public static void main(String[] args) {      List<Frob> list = new ArrayList<Frob>();      Map<Frob,Fnorkle> map = new HashMap<Frob,Fnorkle>();      Quark<Fnorkle> quark = new Quark<Fnorkle>();      Particle<Long,Double> p = new Particle<Long,Double>();      System.out.println(Arrays.toString(        list.getClass().getTypeParameters()));      System.out.println(Arrays.toString(        map.getClass().getTypeParameters()));      System.out.println(Arrays.toString(        quark.getClass().getTypeParameters()));      System.out.println(Arrays.toString(        p.getClass().getTypeParameters()));    }  } /* Output:  [E]  [K, V]  [Q]  [POSITION, MOMENTUM]  *///:~

??????????????????????????
Java?????????????????????????????????????????????????????????

15.7.1 C++???

public class HasF {    public void f() { System.out.println("HasF.f()"); }  } ///:~
//: generics/Manipulation.java  // {CompileTimeError} (Won't compile)    class Manipulator<T> {    private T obj;    public Manipulator(T x) { obj = x; }    // Error: cannot find symbol: method f():    public void manipulate() {/* obj.f();??????*/ }  }    public class Manipulation {    public static void main(String[] args) {      HasF hf = new HasF();      Manipulator<HasF> manipulator =        new Manipulator<HasF>(hf);      manipulator.manipulate();    }  } ///:~

]???????Java??????manipulate()?????obj???f()???????HasF??f()?????
????f()?????extends????

class Manipulator2<T extends HasF> {    private T obj;    public Manipulator2(T x) { obj = x; }    public void manipulate() { obj.f(); }  } ///:~

???????????????????????????????????????????????????????????????T????HasF???????????HasF???T???

?????????????????????????——?????????????????????

class ReturnGenericType<T extends HasF> {    private T obj;    public ReturnGenericType(T x) { obj = x; }    public T get() { return obj; }  } ///:~

15.7.2 ?????

????????????????????????????????????Java??????????????????Java???????????
?????????????????????????????????????????????????????????????????????????????????????????????????????List< T >????????????List??????????????????????Object?
???????????????????????????????????????

15.7.3 ?????

???????????????????????????????????????????????Java???
?????

class Foo<T>{  T var;  }  Foo<Cat> f=new Foo<Cat>();

????????????????T??????????????????????????Object?

//: generics/ErasureAndInheritance.java    class GenericBase<T> {    private T element;    public void set(T arg) { arg = element; }    public T get() { return element; }  }  class Derived1<T> extends GenericBase<T> {}  class Derived2 extends GenericBase {} // No warning  // class Derived3 extends GenericBase<?> {}  // Strange error:  //   unexpected type found : ?  //   required: class or interface without bounds  public class ErasureAndInheritance {    @SuppressWarnings("unchecked")    public static void main(String[] args) {      Derived2 d2 = new Derived2();      Object obj = d2.get();      d2.set(obj); // Warning here!    }  } ///:~
@SuppressWarnings("unchecked")

??????????????????????????????????????????????????????????????????????????????

15.7.4 ??????

???????????????????????????????????

//: generics/ArrayMaker.java  import java.lang.reflect.*;  import java.util.*;    public class ArrayMaker<T> {    private Class<T> kind;    public ArrayMaker(Class<T> kind) { this.kind = kind; }    @SuppressWarnings("unchecked")    T[] create(int size) {      return (T[])Array.newInstance(kind, size);    }    public static void main(String[] args) {      ArrayMaker<String> stringMaker =        new ArrayMaker<String>(String.class);      String[] stringArray = stringMaker.create(9);  System.out.println(Arrays.toString(stringArray));    }  } /* Output:  [null, null, null, null, null, null, null, null, null]  *///:~

?????????Array.newInstance()??????

import java.util.*;    public class ListMaker<T> {    List<T> create() { //????<T>????,?????????????<T>      return new ArrayList<T>();    }    public static void main(String[] args) {      ListMaker<String> stringMaker= new ListMaker<String>();      List<String> stringList = stringMaker.create();    }  } ///:~

???list?????????????

import java.util.*;    public class FilledListMaker<T> {    List<T> create(T t, int n) {      List<T> result = new ArrayList<T>();      for(int i = 0; i < n; i++)        result.add(t);      return result;    }    public static void main(String[] args) {      FilledListMaker<String> stringMaker =        new FilledListMaker<String>();      List<String> list = stringMaker.create("Hello", 4);      System.out.println(list);    }  } /* Output:  [Hello, Hello, Hello, Hello]  *///:~

?????????????create()??T??????????????????????result??????T???????ArrayList< T >???????????????????????????????????????????????????
??????????????????????????????????????????
???????????????——???????????????????????????????????????????

15.8 ?????

??????????????????????????????????????????????

public class Erased<T> {    private final int SIZE = 100;    public static void f(Object arg) {//????????????      if(arg instanceof T) {}          // Error      T var = new T();                 // Error new T???????????????????????????T???????      T[] array = new T[SIZE];         // Error      T[] array = (T)new Object[100]; // Unchecked warning    }  } ///:~

???????????????????isInstance()?

class Building {}  class House extends Building {}    public class ClassTypeCapture<T> {    Class<T> kind;    public ClassTypeCapture(Class<T> kind) {      this.kind = kind;    }    public boolean f(Object arg) {      return kind.isInstance(arg);    }    public static void main(String[] args) {      ClassTypeCapture<Building> ctt1 =        new ClassTypeCapture<Building>(Building.class);      System.out.println(ctt1.f(new Building()));      System.out.println(ctt1.f(new House()));      ClassTypeCapture<House> ctt2 =        new ClassTypeCapture<House>(House.class);      System.out.println(ctt2.f(new Building()));      System.out.println(ctt2.f(new House()));    }  } /* Output:  true  true  false  true  *///:~

15.8.1 ??????

?????????????????????

import static net.mindview.util.Print.*;  class ClassAsFactory<T> {    T x;    public ClassAsFactory(Class<T> kind) {      try {        x = kind.newInstance();      } catch(Exception e) {        throw new RuntimeException(e);      }    }  }  class Employee {}  public class InstantiateGenericType {    public static void main(String[] args) {      ClassAsFactory<Employee> fe =        new ClassAsFactory<Employee>(Employee.class);      print("ClassAsFactory<Employee> succeeded");      try {        ClassAsFactory<Integer> fi =          new ClassAsFactory<Integer>(Integer.class);//???????Integer?????????      } catch(Exception e) {        print("ClassAsFactory<Integer> failed");      }    }  } /* Output:  ClassAsFactory<Employee> succeeded  ClassAsFactory<Integer> failed  *///:~

??????????????

interface FactoryI<T> {    T create();  }  class Foo2<T> {    private T x;    public <F extends FactoryI<T>> Foo2(F factory) {      x = factory.create();    }    // ...  }  class IntegerFactory implements FactoryI<Integer> {    public Integer create() {      return new Integer(0);    }  }  class Widget {    public static class Factory implements FactoryI<Widget> {      public Widget create() {        return new Widget();      }    }  }  public class FactoryConstraint {    public static void main(String[] args) {      new Foo2<Integer>(new IntegerFactory());      new Foo2<Widget>(new Widget.Factory());    }  } ///:~

?????????

abstract class GenericWithCreate<T> {    final T element;    GenericWithCreate() { element = create(); }    abstract T create();  }    class X {}    class Creator extends GenericWithCreate<X> {    X create() { return new X(); }    void f() {      System.out.println(element.getClass().getSimpleName());    }  }    public class CreatorGeneric {    public static void main(String[] args) {      Creator c = new Creator();      c.f();    }  } /* Output:  X  *///:~

15.8.2 ????

??????????????????????????????????ArrayList?

import java.util.*;    public class ListOfGenerics<T> {    private List<T> array = new ArrayList<T>();    public void add(T item) { array.add(item); }    public T get(int index) { return array.get(index); }  } ///:~

??????????????????

class Generic<T> {}  public class ArrayOfGenericReference {    static Generic<Integer>[] gia;  } ///:~

??????????????????
????Object????????????????????????????????

public class ArrayOfGeneric {    static final int SIZE = 100;    static Generic<Integer>[] gia;    @SuppressWarnings("unchecked")    public static void main(String[] args) {      // Compiles; produces ClassCastException:      // gia = (Generic<Integer>[])new Object[SIZE]; //?????      // Runtime type is the raw (erased) type:      gia = (Generic<Integer>[])new Generic[SIZE];      System.out.println(gia.getClass().getSimpleName());      gia[0] = new Generic<Integer>();      //! gia[1] = new Object(); // Compile-time error      // Discovers type mismatch at compile time:      //! gia[2] = new Generic<Double>();    }  } /* Output:  Generic[]  *///:~

???????????????????????????????????

public class GenericArray<T> {    private T[] array;    @SuppressWarnings("unchecked")    public GenericArray(int sz) {      array = (T[])new Object[sz];    }//??Object???T    public void put(int index, T item) {      array[index] = item;    }    public T get(int index) { return array[index]; }    // Method that exposes the underlying representation:    public T[] rep() { return array; }    public static void main(String[] args) {      GenericArray<Integer> gai =        new GenericArray<Integer>(10);      // This causes a ClassCastException:      //! Integer[] ia = gai.rep();      // This is OK:      Object[] oa = gai.rep();    }  } ///:~

????T[] array=new T[sz]??????????????????????
???????????????????Object[]????????????T[]????????????????????????????????????????????????????Object[]??????????????????T????

public class GenericArray2<T> {    private Object[] array;    public GenericArray2(int sz) {      array = new Object[sz];    }    public void put(int index, T item) {      array[index] = item;    }    @SuppressWarnings("unchecked")    public T get(int index) { return (T)array[index]; }    @SuppressWarnings("unchecked")    public T[] rep() {      return (T[])array; // Warning: unchecked cast    }    public static void main(String[] args) {      GenericArray2<Integer> gai =        new GenericArray2<Integer>(10);      for(int i = 0; i < 10; i ++)        gai.put(i, i);      for(int i = 0; i < 10; i ++)        System.out.print(gai.get(i) + " ");      System.out.println();      try {        Integer[] ia = gai.rep();      } catch(Exception e) { System.out.println(e); }    }  } /* Output: (Sample)  0 1 2 3 4 5 6 7 8 9  java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;  *///:~

????array??Object[]???T[]???????????????????????????????????
?????????????????

import java.lang.reflect.*;    public class GenericArrayWithTypeToken<T> {    private T[] array;    @SuppressWarnings("unchecked")    public GenericArrayWithTypeToken(Class<T> type, int sz) {      array = (T[])Array.newInstance(type, sz);    }    public void put(int index, T item) {      array[index] = item;    }    public T get(int index) { return array[index]; }    // Expose the underlying representation:    public T[] rep() { return array; }    public static void main(String[] args) {      GenericArrayWithTypeToken<Integer> gai =        new GenericArrayWithTypeToken<Integer>(          Integer.class, 10);      // This now works:      for(int i=0;i<10;i++)        gai.put(i,i);      Integer[] ia = gai.rep();      for (int i:ia )        System.out.println(i);    }  } ///:~

????Class< T >?????????????????????????????????????

15.9 ??

????????????????????????????????????????????????????????????????????????????????
?????????????????i???????????????????Object?????????????????????????????????????????????????????Java?????extends????

interface HasColor { java.awt.Color getColor(); }    class Colored<T extends HasColor> {    T item;    Colored(T item) { this.item = item; }    T getItem() { return item; }    // The bound allows you to call a method:    java.awt.Color color() { return item.getColor(); }  }    class Dimension { public int x, y, z; }    // This won't work -- class must be first, then interfaces:  // class ColoredDimension<T extends HasColor & Dimension> {    // Multiple bounds:  class ColoredDimension<T extends Dimension & HasColor> {    T item;    ColoredDimension(T item) { this.item = item; }    T getItem() { return item; }    java.awt.Color color() { return item.getColor(); }    int getX() { return item.x; }    int getY() { return item.y; }    int getZ() { return item.z; }  }    interface Weight { int weight(); }    // As with inheritance, you can have only one  // concrete class but multiple interfaces:  class Solid<T extends Dimension & HasColor & Weight> {    T item;    Solid(T item) { this.item = item; }    T getItem() { return item; }    java.awt.Color color() { return item.getColor(); }    int getX() { return item.x; }    int getY() { return item.y; }    int getZ() { return item.z; }    int weight() { return item.weight(); }  }    class Bounded  extends Dimension implements HasColor, Weight {    public java.awt.Color getColor() { return null; }    public int weight() { return 0; }  }    public class BasicBounds {    public static void main(String[] args) {      Solid<Bounded> solid =        new Solid<Bounded>(new Bounded());     solid.color();     solid.getY();     solid.weight();    }  } ///:~

????????????

class HoldItem<T> {    T item;    HoldItem(T item) { this.item = item; }    T getItem() { return item; }  }  class Colored2<T extends HasColor> extends HoldItem<T> {    Colored2(T item) { super(item); }    java.awt.Color color() { return item.getColor(); }  }  class ColoredDimension2<T extends Dimension & HasColor>  extends Colored2<T> {    ColoredDimension2(T item) {  super(item); }    int getX() { return item.x; }    int getY() { return item.y; }    int getZ() { return item.z; }  }  class Solid2<T extends Dimension & HasColor & Weight>  extends ColoredDimension2<T> {    Solid2(T item) {  super(item); }    int weight() { return item.weight(); }  }  public class InheritBounds {    public static void main(String[] args) {      Solid2<Bounded> solid2 =        new Solid2<Bounded>(new Bounded());      solid2.color();      solid2.getY();      solid2.weight();    }  } ///:~

????????

// Demonstrating bounds in Java generics.  import java.util.*;    interface SuperPower {}  interface XRayVision extends SuperPower {    void seeThroughWalls();  }  interface SuperHearing extends SuperPower {    void hearSubtleNoises();  }  interface SuperSmell extends SuperPower {    void trackBySmell();  }    class SuperHero<POWER extends SuperPower> {    POWER power;    SuperHero(POWER power) { this.power = power; }    POWER getPower() { return power; }  }    class SuperSleuth<POWER extends XRayVision>//POWER?????XRayVision???  extends SuperHero<POWER> {    SuperSleuth(POWER power) { super(power); }    void see() { power.seeThroughWalls(); }  }    class CanineHero<POWER extends SuperHearing & SuperSmell>  extends SuperHero<POWER> {    CanineHero(POWER power) { super(power); }    void hear() { power.hearSubtleNoises(); }    void smell() { power.trackBySmell(); }  }    class SuperHearSmell implements SuperHearing, SuperSmell {    public void hearSubtleNoises() {}    public void trackBySmell() {}  }    class DogBoy extends CanineHero<SuperHearSmell> {    DogBoy() { super(new SuperHearSmell()); }  }    public class EpicBattle {    // Bounds in generic methods:    static <POWER extends SuperHearing>    void useSuperHearing(SuperHero<POWER> hero) {      hero.getPower().hearSubtleNoises();    }    static <POWER extends SuperHearing & SuperSmell>    void superFind(SuperHero<POWER> hero) {      hero.getPower().hearSubtleNoises();      hero.getPower().trackBySmell();    }    public static void main(String[] args) {      DogBoy dogBoy = new DogBoy();      useSuperHearing(dogBoy);      superFind(dogBoy);      // You can do this:      List<? extends SuperHearing> audioBoys;      // But you can't do this:      // List<? extends SuperHearing & SuperSmell> dogBoys;    }  } ///:~

15.10 ???

?????????????????????

class Fruit {}  class Apple extends Fruit {}  class Jonathan extends Apple {}  class Orange extends Fruit {}    public class CovariantArrays {    public static void main(String[] args) {      Fruit[] fruit = new Apple[10];      fruit[0] = new Apple(); // OK      fruit[1] = new Jonathan(); // OK      // Runtime type is Apple[], not Fruit[] or Orange[]:      try {        // Compiler allows you to add Fruit:        fruit[2] = new Fruit(); // ArrayStoreException ??????      } catch(Exception e) { System.out.println(e); }      try {        // Compiler allows you to add Oranges:        fruit[3] = new Orange(); // ArrayStoreException      } catch(Exception e) { System.out.println(e); }    }  } /* Output:  java.lang.ArrayStoreException: Fruit  java.lang.ArrayStoreException: Orange  *///:~

???????????????????????

import java.util.*;  public class NonCovariantGenerics {    // Compile Error: incompatible types:    List<Fruit> flist = new ArrayList<Apple>();//?????Apple???????Fruit??  } ///:~

???????????????????????????????????????????????????????

import java.util.*;  public class GenericsAndCovariance {    public static void main(String[] args) {      // Wildcards allow covariance:      List<? extends Fruit> flist = new ArrayList<Apple>();//??????????????????????????????????Object???????      // Compile Error: can't add any type of object:      // flist.add(new Apple());      // flist.add(new Fruit());      // flist.add(new Object());      flist.add(null); // Legal but uninteresting      // We know that it returns at least Fruit:      Fruit f = flist.get(0);    }  } ///:~

15.10.1 ???????

import java.util.*;    public class CompilerIntelligence {    public static void main(String[] args) {      List<? extends Fruit> flist =        Arrays.asList(new Apple());      Apple a = (Apple)flist.get(0); // No warning      flist.contains(new Apple()); // ?????Object      flist.indexOf(new Apple()); // Argument is 'Object'      //flist.add(new Apple());??Add??????? extends Fruit?????????????????????????????    }  } ///:~

add()???????????????????contains()?indexOf()???Object??????????????ArrayList<? extends Fruit>??add()???????? extends Fruit?

public class Holder<T> {    private T value;    public Holder() {}    public Holder(T val) { value = val; }    public void set(T val) { value = val; }    public T get() { return value; }    public boolean equals(Object obj) {      return value.equals(obj);    }    public static void main(String[] args) {      Holder<Apple> Apple = new Holder<Apple>(new Apple());      Apple d = Apple.get();      Apple.set(d);      // Holder<Fruit> Fruit = Apple; // Cannot upcast      Holder<? extends Fruit> fruit = Apple; // OK      Fruit p = fruit.get();      d = (Apple)fruit.get(); // Returns 'Object'      try {        Orange c = (Orange)fruit.get(); // No warning      } catch(Exception e) { System.out.println(e); }      // fruit.set(new Apple()); // Cannot call set()      // fruit.set(new Fruit()); // Cannot call set()      System.out.println(fruit.equals(d)); // OK    }  } /* Output: (Sample)  java.lang.ClassCastException: Apple cannot be cast to Orange  true  *///:~

15.10.2 ??

????????????????????????????????????<? super MyClass>,????????<? super T>?

import java.util.*;  public class SuperTypeWildcards {    static void writeTo(List<? super Apple> apples) {      apples.add(new Apple());      apples.add(new Jonathan());      // apples.add(new Fruit()); // Error    }  } ///:~

??????????????????????????

import java.util.*;    public class GenericWriting {    static <T> void writeExact(List<T > list, T item) {      list.add(item);    }    static List<Apple> apples = new ArrayList<Apple>();    static List<Fruit> fruit = new ArrayList<Fruit>();    static void f1() {      writeExact(apples, new Apple());      // writeExact(fruit, new Apple()); // Error:      // Incompatible types: found Fruit, required Apple    }    static <T> void    writeWithWildcard(List<? super T> list, T item) {      list.add(item);    }    static void f2() {      writeWithWildcard(apples, new Apple());      writeWithWildcard(fruit, new Apple());    }    public static void main(String[] args) { f1(); f2(); }  } ///:~

15.10.3 ?????

?????< ? >????????????????????????????????

import java.util.*;    public class UnboundedWildcards1 {    static List list1;    static List<?> list2;    static List<? extends Object> list3;    static void assign1(List list) {      list1 = list;      list2 = list;      // list3 = list; // Warning: unchecked conversion      // Found: List, Required: List<? extends Object>    }    static void assign2(List<?> list) {      list1 = list;      list2 = list;      list3 = list;    }    static void assign3(List<? extends Object> list) {      list1 = list;      list2 = list;      list3 = list;    }    public static void main(String[] args) {      assign1(new ArrayList());      assign2(new ArrayList());      // assign3(new ArrayList()); // Warning:      // Unchecked conversion. Found: ArrayList      // Required: List<? extends Object>      assign1(new ArrayList<String>());      assign2(new ArrayList<String>());      assign3(new ArrayList<String>());      // Both forms are acceptable as List<?>:      List<?> wildList = new ArrayList();      wildList = new ArrayList<String>();      assign1(wildList);      assign2(wildList);      assign3(wildList);    }  } ///:~

< ? >?????????????????????????Java?????????????????????????????????????????????????

import java.util.*;    public class UnboundedWildcards2 {    static Map map1;    static Map<?,?> map2;    static Map<String,?> map3;    static void assign1(Map map) { map1 = map; }    static void assign2(Map<?,?> map) { map2 = map; }    static void assign3(Map<String,?> map) { map3 = map; }    public static void main(String[] args) {      assign1(new HashMap());      assign2(new HashMap());      assign3(new HashMap()); // Warning:      // Unchecked conversion. Found: HashMap      // Required: Map<String,?>      assign1(new HashMap<String,Integer>());      assign2(new HashMap<String,Integer>());      assign3(new HashMap<String,Integer>());    }  } ///:~

????????????????????????LIst<?>??????LIst< Object >??List?????List< Object >——???????????List?????????Object?????List??List<?>??????????????List?

//: generics/Wildcards.java  // Exploring the meaning of wildcards.    public class Wildcards {     // Raw argument:    static void rawArgs(Holder holder, Object arg) {       holder.set(arg); // Warning:?????Holder???????set??Object?????      //   Unchecked call to set(T) as a      //   member of the raw type Holder      // holder.set(new Wildcards()); // Same warning        // Can't do this; don't have any 'T':      // T t = holder.get();        // OK, but type information has been lost:      Object obj = holder.get();    }    // Similar to rawArgs(), but errors instead of warnings:    static void unboundedArg(Holder<?> holder, Object arg) {      // holder.set(arg); // Error:????????????????Holder<?>???????????????????????????Object?      //   set(capture of ?) in Holder<capture of ?>      //   cannot be applied to (Object)      // holder.set(new Wildcards()); // Same error        // Can't do this; don't have any 'T':      // T t = holder.get();        // OK, but type information has been lost:      Object obj = holder.get();    }    static <T> T exact1(Holder<T> holder) {      T t = holder.get();      return t;    }    static <T> T exact2(Holder<T> holder, T arg) {      holder.set(arg);      T t = holder.get();      return t;    }    static <T>    T wildSubtype(Holder<? extends T> holder, T arg) {      // holder.set(arg); // Error:?????????????????????????      //   set(capture of ? extends T) in      //   Holder<capture of ? extends T>      //   cannot be applied to (T)      T t = holder.get();      return t;    }    static <T>    void wildSupertype(Holder<? super T> holder, T arg) {      holder.set(arg);//????????T?????????      // T t = holder.get();  // Error:      //   Incompatible types: found Object, required T        // OK, but type information has been lost:      Object obj = holder.get();//??????????????????????Object??????    }    public static void main(String[] args) {      Holder raw = new Holder<Long>();      // Or:      raw = new Holder();      Holder<Long> qualified = new Holder<Long>();      Holder<?> unbounded = new Holder<Long>();      Holder<? extends Long> bounded = new Holder<Long>();      Long lng = 1L;        rawArgs(raw, lng);      rawArgs(qualified, lng);      rawArgs(unbounded, lng);      rawArgs(bounded, lng);        unboundedArg(raw, lng);      unboundedArg(qualified, lng);      unboundedArg(unbounded, lng);      unboundedArg(bounded, lng);         Object r1 = exact1(raw); // Warnings:      //   Unchecked conversion from Holder to Holder<T>      //   Unchecked method invocation: exact1(Holder<T>)      //   is applied to (Holder)      Long r2 = exact1(qualified);      Object r3 = exact1(unbounded); // Must return Object      Long r4 = exact1(bounded);         Long r5 = exact2(raw, lng); // Warnings:      //   Unchecked conversion from Holder to Holder<Long>      //   Unchecked method invocation: exact2(Holder<T>,T)      //   is applied to (Holder,Long)      Long r6 = exact2(qualified, lng);      // Long r7 = exact2(unbounded, lng); // Error:      //   exact2(Holder<T>,T) cannot be applied to      //   (Holder<capture of ?>,Long)      // Long r8 = exact2(bounded, lng); // Error:      //   exact2(Holder<T>,T) cannot be applied      //   to (Holder<capture of ? extends Long>,Long)        // Long r9 = wildSubtype(raw, lng); // Warnings:      //   Unchecked conversion from Holder      //   to Holder<? extends Long>      //   Unchecked method invocation:      //   wildSubtype(Holder<? extends T>,T) is      //   applied to (Holder,Long)      Long r10 = wildSubtype(qualified, lng);      // OK, but can only return Object:      Object r11 = wildSubtype(unbounded, lng);      Long r12 = wildSubtype(bounded, lng);        // wildSupertype(raw, lng); // Warnings:      //   Unchecked conversion from Holder      //   to Holder<? super Long>      //   Unchecked method invocation:      //   wildSupertype(Holder<? super T>,T)      //   is applied to (Holder,Long)      wildSupertype(qualified, lng);      // wildSupertype(unbounded, lng); // Error:      //   wildSupertype(Holder<? super T>,T) cannot be      //   applied to (Holder<capture of ?>,Long)      // wildSupertype(bounded, lng); // Error:      //   wildSupertype(Holder<? super T>,T) cannot be      //  applied to (Holder<capture of ? extends Long>,Long)    }  } ///:~

??????????????????????????????????????????????????????????????

15.10.4 ????

???????????<?>???????????????<?>????????????????????????????????????????????????????????????????????????????????????????????

public class CaptureConversion {    static <T> void f1(Holder<T> holder) {//?????????????      T t = holder.get();      System.out.println(t.getClass().getSimpleName());    }    static void f2(Holder<?> holder) {//????????????????????f1.?????????f2???????????????f1????????      f1(holder); // Call with captured type    }    @SuppressWarnings("unchecked")    public static void main(String[] args) {      Holder raw = new Holder<Integer>(1);       f1(raw); // Produces warnings      f2(raw); // No warnings      Holder rawBasic = new Holder();      rawBasic.set(new Object()); // Warning      f2(rawBasic); // No warnings      // Upcast to Holder<?>, still figures it out:      Holder<?> wildcarded = new Holder<Double>(1.0);      f2(wildcarded);    }  } /* Output:  Integer  Object  Double  *///:~

15.11 ??

15.11.1 ???????????????

???????????

import java.util.*;    public class ListOfInt {    public static void main(String[] args) {      List<Integer> li = new ArrayList<Integer>();      for(int i = 0; i < 5; i++)        li.add(i);      for(int i : li)        System.out.print(i + " ");    }  } /* Output:  0 1 2 3 4  *///:~

????????????????????????????Org.apache.commons.collections.primitives?
?????????Byte?Set?

import java.util.*;    public class ByteSet {    Byte[] possibles = { 1,2,3,4,5,6,7,8,9 };    Set<Byte> mySet =      new HashSet<Byte>(Arrays.asList(possibles));    // But you can't do this:    // Set<Byte> mySet2 = new HashSet<Byte>(    //   Arrays.<Byte>asList(1,2,3,4,5,6,7,8,9));  } ///:~

????Generator???

import net.mindview.util.*;    // Fill an array using a generator:  class FArray {    public static <T> T[] fill(T[] a, Generator<T> gen) {      for(int i = 0; i < a.length; i++)        a[i] = gen.next();      return a;    }  }  public class PrimitiveGenericTest {    public static void main(String[] args) {      String[] strings = FArray.fill(        new String[8], new RandomGenerator.String());      for(String s : strings)        System.out.println(s);      Integer[] integers = FArray.fill(        new Integer[7], new RandomGenerator.Integer());      for(int i: integers)        System.out.println(i);      // Autoboxing won't save you here. This won't compile:      // int[] b =      //   FArray.fill(new int[7], new RandIntGenerator());    }  } /* Output:  YNzbrnyGcF  OWZnTcQrGs  eGZMmJMRoE  suEcUOneOE  dLsmwHLGEa  hKcxrEqUCB  bkInaMesbt  7052  6665  2654  3909  5202  2209  5458  *///:~

15.11.2 ???????

??????????????????????????????????????????

interface Payable<T> {}    class Employee1 implements Payable<Employee1> {}  class Hourly extends Employee implements Payable<Hourly> {} ///:~???????Object  public class MultipleInterfaceVariants{      public static void main(String[] args){      }  }

15.11.3 ?????

??????????????instanceof????????
???????????????Object???????????????????T?

class FixedSizeStack<T> {    private int index = 0;    private Object[] storage;    public FixedSizeStack(int size) {      storage = new Object[size];    }    public void push(T item) { storage[index++] = item; }    @SuppressWarnings("unchecked")    public T pop() { return (T)storage[--index]; }//???????????????????????????pop()???????????????  }    public class GenericCast {    public static final int SIZE = 10;    public static void main(String[] args) {      FixedSizeStack<String> strings =        new FixedSizeStack<String>(SIZE);      for(String s : "A B C D E F G H I J".split(" "))        strings.push(s);      for(int i = 0; i < SIZE; i++) {        String s = strings.pop();        System.out.print(s + " ");      }    }  } /* Output:  J I H G F E D C B A  *///:~

????????????????????????????????????

import java.io.*;  import java.util.*;    public class NeedCasting {    @SuppressWarnings("unchecked")    public static void main(String[] args) throws Exception {      ObjectInputStream in = new ObjectInputStream(        new FileInputStream(""));      List<Widget> shapes = (List<Widget>)in.readObject();//readObject????????????????????????????    }  } ///:~

???????

import java.io.*;  import java.util.*;    public class ClassCasting {    @SuppressWarnings("unchecked")    public void f(String[] args) throws Exception {      ObjectInputStream in = new ObjectInputStream(        new FileInputStream(args[0]));        // Won't Compile:  //    List<Widget> lw1 =  //    List<Widget>.class.cast(in.readObject());      List<Widget> lw2 = List.class.cast(in.readObject());    }  } ///:~

15.11.4 ??

??????????

import java.util.*;  public class UseList<W,T> {    void f1(List<T> v) {}//????????????    void f1(List<W> v) {}  } ///:~

15.11.5 ???????

?????????????

public class ComparablePet  implements Comparable<ComparablePet> {    public int compareTo(ComparablePet arg) { return 0; }  } ///:~

?????????????????????

class Cat extends ComparablePet implements Comparable<Cat>{    // Error: Comparable cannot be inherited with    // different arguments: <Cat> and <Pet>    public int compareTo(Cat arg) { return 0; }  } ///:~

???????????????????????

class Hamster extends ComparablePet  implements Comparable<ComparablePet> {    public int compareTo(ComparablePet arg) { return 0; }  }  // Or just:  class Gecko extends ComparablePet {    public int compareTo(ComparablePet arg) { return 0; }  } ///:~

15.12 ??????

?Java????????????????????

class SelfBounded<T extends SelfBounded<T>>

????????????????????????????SelfBounded???????T??T?????????????????T?????SelfBounded?

15.12.1 ???????

???????????????????????????????????????

class GenericType<T> {}    public class CuriouslyRecurringGeneric    extends GenericType<CuriouslyRecurringGeneric> {} ///:~

????????????
Java????????????????????????????????????????????????????????????????Object????

public class BasicHolder<T> {    T element;    void set(T arg) { element = arg; }    T get() { return element; }    void f() {      System.out.println(element.getClass().getSimpleName());    }  } ///:~

?????????????????????????????

class Subtype extends BasicHolder<Subtype> {}    public class CRGWithBasicHolder {    public static void main(String[] args) {      Subtype st1 = new Subtype(), st2 = new Subtype();      st1.set(st2);      Subtype st3 = st1.get();      st1.f();    }  } /* Output:  Subtype  *///:~

CRG??????????????
?????????????????????

15.12.2 ???

BasicHolder????????????????

class Other {}  class BasicOther extends BasicHolder<Other> {}    public class Unconstrained {    public static void main(String[] args) {      BasicOther b = new BasicOther(), b2 = new BasicOther();      b.set(new Other());      Other other = b.get();      b.f();    }  } /* Output:  Other  *///:~

??????????????????????????????

class SelfBounded<T extends SelfBounded<T>> {    T element;    SelfBounded<T> set(T arg) {      element = arg;      return this;    }    T get() {System.out.println(this.getClass().getSimpleName()); return element; }  }  class A extends SelfBounded<A> {}//?????????????????????  class B extends SelfBounded<A> {} // Also OK  class C extends SelfBounded<C> {    C setAndGet(C arg) { set(arg); return get(); }  }  class D {}  // Can't do this:   //class E extends SelfBounded<D> {}  // Compile error: Type parameter D is not within its bound  // Alas, you can do this, so you can't force the idiom:  class F extends SelfBounded {}//??????????????  public class SelfBounding {    public static void main(String[] args) {      A a = new A();      a.set(new A());      a = a.set(new A()).get();      a = a.get();      C c = new C();      c = c.setAndGet(new C());    }  } ///:~

??????????????????????????????
???????????????????????????

public class NotSelfBounded<T> {    T element;    NotSelfBounded<T> set(T arg) {      element = arg;      return this;    }    T get() { return element; }  }  class A2 extends NotSelfBounded<A2> {}  class B2 extends NotSelfBounded<A2> {}    class C2 extends NotSelfBounded<C2> {    C2 setAndGet(C2 arg) { set(arg); return get(); }  }  class D2 {}  // Now this is OK:  class E2 extends NotSelfBounded<D2> {} ///:~

???????????????????????????????????????????????????????????????
??????????????

public class SelfBoundingMethods {    static <T extends SelfBounded<T>> T f(T arg) {      return arg.set(arg).get();    }    public static void main(String[] args) {      A a = f(new A());    }  } ///:~

15.12.3 ????

??????????????????????——??????????????

class Base {}  class Derived extends Base {}  interface OrdinaryGetter {    Base get();  }  interface DerivedGetter extends OrdinaryGetter {    // Return type of overridden method is allowed to vary:    Derived get();  }  public class CovariantReturnTypes {    void test(DerivedGetter d) {      Derived d2 = d.get();    }  } ///:~

?????????????????????????

interface GenericGetter<T extends GenericGetter<T>> {    T get();  }  interface Getter extends GenericGetter<Getter> {}  public class GenericsAndReturnTypes {    void test(Getter g) {      Getter result = g.get();      GenericGetter gg = g.get(); // Also the base type    }  } ///:~

???????????????????????????????????????????

interface SelfBoundSetter<T extends SelfBoundSetter<T>> {    void set(T arg);  }  interface Setter extends SelfBoundSetter<Setter> {}  public class SelfBoundingAndCovariantArguments {    void testA(Setter s1, Setter s2, SelfBoundSetter sbs) {      s1.set(s2);      // s1.set(sbs); // Error:??????????????????set()??????????????????????????????????      // set(Setter) in SelfBoundSetter<Setter>      // cannot be applied to (SelfBoundSetter)    }  } ///:~

??????????????????????????????

class GenericSetter<T> { // Not self-bounded    void set(T arg){      System.out.println("GenericSetter.set(Base)");    }  }  class DerivedGS extends GenericSetter<Base> {    void set(Derived derived){      System.out.println("DerivedGS.set(Derived)");    }  }  public class PlainGenericInheritance {    public static void main(String[] args) {      Base base = new Base();      Derived derived = new Derived();      DerivedGS dgs = new DerivedGS();      dgs.set(derived);      dgs.set(base); // Compiles: overloaded, not overridden!    }  } /* Output:  DerivedGS.set(Derived)  GenericSetter.set(Base)  *///:~

???????????????????????????????????????????????????

15.13 ??????

Java SE5?java.util.Collections?????????????????checkedCollection()?checkedList(),checkedMap(),checkedSet(),checkedSortedMap()?checkedSortedSet()????????????????????????????????????????????????????

import pets.*;  import java.util.*;    public class CheckedList {    @SuppressWarnings("unchecked")    static void oldStyleMethod(List probablyDogs) {      probablyDogs.add(new Cat());    }    public static void main(String[] args) {        List<Dog> dogs1 = new ArrayList<Dog>();      oldStyleMethod(dogs1); // Quietly accepts a Cat      List<Dog> dogs2 = Collections.checkedList(              new ArrayList<Dog>(), Dog.class);      try {        oldStyleMethod(dogs2); // Throws an exception?????      } catch(Exception e) {        System.out.println(e);      }      // Derived types work fine:      List<Pet> pets = Collections.checkedList(//??????????????????              new ArrayList<Pet>(), Pet.class);      pets.add(new Dog());      pets.add(new Cat());    }  } /* Output:  java.lang.ClassCastException: Attempt to insert class typeinfo.pets.Cat element into collection with element type class typeinfo.pets.Dog  *///:~

15.14 ??

???????????????????????catch??????????????????????????????????????????????????Throwable?

import java.util.*;    interface Processor<T,E extends Exception> {    void process(List<T> resultCollector) throws E;  }  class ProcessRunner<T,E extends Exception>  extends ArrayList<Processor<T,E>> {    List<T> processAll() throws E {      List<T> resultCollector = new ArrayList<T>();      for(Processor<T,E> processor : this)        processor.process(resultCollector);      return resultCollector;    }  }  class Failure1 extends Exception {}  class Processor1 implements Processor<String,Failure1> {    static int count = 3;    public void    process(List<String> resultCollector) throws Failure1 {      if(count-- > 1)        resultCollector.add("Hep!");      else        resultCollector.add("Ho!");      if(count < 0)         throw new Failure1();    }  }  class Failure2 extends Exception {}  class Processor2 implements Processor<Integer,Failure2> {    static int count = 2;    public void    process(List<Integer> resultCollector) throws Failure2 {      if(count-- == 0)        resultCollector.add(47);      else {        resultCollector.add(11);      }      if(count < 0)         throw new Failure2();    }  }  public class ThrowGenericException {    public static void main(String[] args) {      ProcessRunner<String,Failure1> runner =        new ProcessRunner<String,Failure1>();      for(int i = 0; i < 3; i++)        runner.add(new Processor1());      try {        System.out.println(runner.processAll());      } catch(Failure1 e) {        System.out.println(e);      }      ProcessRunner<Integer,Failure2> runner2 =        new ProcessRunner<Integer,Failure2>();      for(int i = 0; i < 3; i++)        runner2.add(new Processor2());      try {        System.out.println(runner2.processAll());      } catch(Failure2 e) {        System.out.println(e);      }    }  } ///:~

15.15 ??

?????????????????????????????????
????????????????????????????????????????????????????????????????????????????

15.15.2 ?????

import java.util.*;    interface TimeStamped { long getStamp(); }    class TimeStampedImp implements TimeStamped {    private final long timeStamp;    public TimeStampedImp() {      timeStamp = new Date().getTime();    }    public long getStamp() { return timeStamp; }  }    interface SerialNumbered { long getSerialNumber(); }    class SerialNumberedImp implements SerialNumbered {    private static long counter = 1;    private final long serialNumber = counter++;    public long getSerialNumber() { return serialNumber; }  }    interface Basic {    public void set(String val);    public String get();  }    class BasicImp implements Basic {    private String value;    public void set(String val) { value = val; }    public String get() { return value; }  }    class Mixin extends BasicImp  implements TimeStamped, SerialNumbered {//???????????????Mixin????????????Mixin??????????????????????    private TimeStamped timeStamp = new TimeStampedImp();    private SerialNumbered serialNumber =      new SerialNumberedImp();    public long getStamp() { return timeStamp.getStamp(); }    public long getSerialNumber() {      return serialNumber.getSerialNumber();    }  }    public class Mixins {    public static void main(String[] args) {      Mixin mixin1 = new Mixin(), mixin2 = new Mixin();      mixin1.set("test string 1");      mixin2.set("test string 2");      System.out.println(mixin1.get() + " " +        mixin1.getStamp() +  " " + mixin1.getSerialNumber());      System.out.println(mixin2.get() + " " +        mixin2.getStamp() +  " " + mixin2.getSerialNumber());    }  } /* Output: (Sample)  test string 1 1132437151359 1  test string 2 1132437151359 2  *///:~

15.15.3 ???????

?????????????????????????????????????????????????????????????????????
??????????????????????????????????????????????????????????????????????????????????????????????????
???????????????????????????????
???????????????

package decorator;  import java.util.*;  class Basic {    private String value;    public void set(String val) { value = val; }    public String get() { return value; }  }  class Decorator extends Basic {    protected Basic basic;    public Decorator(Basic basic) { this.basic = basic; }    public void set(String val) { basic.set(val); }    public String get() { return basic.get(); }  }  class TimeStamped extends Decorator {    private final long timeStamp;    public TimeStamped(Basic basic) {      super(basic);      timeStamp = new Date().getTime();    }    public long getStamp() { return timeStamp; }  }  class SerialNumbered extends Decorator {    private static long counter = 1;    private final long serialNumber = counter++;    public SerialNumbered(Basic basic) { super(basic); }    public long getSerialNumber() { return serialNumber; }  }  public class Decoration {    public static void main(String[] args) {      TimeStamped t = new TimeStamped(new Basic());      TimeStamped t2 = new TimeStamped(        new SerialNumbered(new Basic()));      //! t2.getSerialNumber(); // Not available      SerialNumbered s = new SerialNumbered(new Basic());      SerialNumbered s2 = new SerialNumbered(        new TimeStamped(new Basic()));      //! s2.getStamp(); // Not available    }  } ///:~

??????????????????????????????????????????????????????????????????????????????????????

15.15.4 ???????

????????????????????????????????????????????????????????????

import java.lang.reflect.*;  import java.util.*;  import net.mindview.util.*;  import static net.mindview.util.Tuple.*;    class MixinProxy implements InvocationHandler {    Map<String,Object> delegatesByMethod;    public MixinProxy(TwoTuple<Object,Class<?>>... pairs) {      delegatesByMethod = new HashMap<String,Object>();      for(TwoTuple<Object,Class<?>> pair : pairs) {        for(Method method : pair.second.getMethods()) {          String methodName = method.getName();          // The first interface in the map          // implements the method.          if (!delegatesByMethod.containsKey(methodName))            delegatesByMethod.put(methodName, pair.first);        }      }    }    public Object invoke(Object proxy, Method method,      Object[] args) throws Throwable {      String methodName = method.getName();      Object delegate = delegatesByMethod.get(methodName);      return method.invoke(delegate, args);    }    @SuppressWarnings("unchecked")    public static Object newInstance(TwoTuple... pairs) {      Class[] interfaces = new Class[pairs.length];      for(int i = 0; i < pairs.length; i++) {        interfaces[i] = (Class)pairs[i].second;      }      ClassLoader cl =        pairs[0].first.getClass().getClassLoader();      return Proxy.newProxyInstance(        cl, interfaces, new MixinProxy(pairs));    }  }  public class DynamicProxyMixin {    public static void main(String[] args) {      Object mixin = MixinProxy.newInstance(        tuple(new BasicImp(), Basic.class),        tuple(new TimeStampedImp(), TimeStamped.class),        tuple(new SerialNumberedImp(),SerialNumbered.class));      Basic b = (Basic)mixin;      TimeStamped t = (TimeStamped)mixin;      SerialNumbered s = (SerialNumbered)mixin;      b.set("Hello");      System.out.println(b.get());      System.out.println(t.getStamp());      System.out.println(s.getSerialNumber());    }  } /* Output: (Sample)  Hello  1132519137015  1  *///:~

15.16 ??????

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????
?????????????????????????????????????????????????????????????????speak()?sit()?????????????????????????
???????????????
????????????????

15.17 ????????????

??Java?????????????????????????????????????????

15.17.1 ??

?????????????

//: generics/LatentReflection.java  // Using Reflection to produce latent typing.  import java.lang.reflect.*;  import static net.mindview.util.Print.*;    // Does not implement Performs:  class Mime {    public void walkAgainstTheWind() {}    public void sit() { print("Pretending to sit"); }    public void pushInvisibleWalls() {}    public String toString() { return "Mime"; }  }    // Does not implement Performs:  class SmartDog {    public void speak() { print("Woof!"); }    public void sit() { print("Sitting"); }    public void reproduce() {}  }    class CommunicateReflectively {    public static void perform(Object speaker) {      Class<?> spkr = speaker.getClass();      try {        try {          Method speak = spkr.getMethod("speak");          speak.invoke(speaker);        } catch(NoSuchMethodException e) {          print(speaker + " cannot speak");        }        try {          Method sit = spkr.getMethod("sit");          sit.invoke(speaker);        } catch(NoSuchMethodException e) {          print(speaker + " cannot sit");        }      } catch(Exception e) {        throw new RuntimeException(speaker.toString(), e);      }    }  }    public class LatentReflection {    public static void main(String[] args) {      CommunicateReflectively.perform(new SmartDog());      CommunicateReflectively.perform(new Robot());      CommunicateReflectively.perform(new Mime());    }  } /* Output:  Woof!  Sitting  Click!  Clank!  Mime cannot speak  Pretending to sit  *///:~

????????????????????????????????????????????????

15.17.2 ??????????

??????????

import java.lang.reflect.*;  import java.util.*;  import static net.mindview.util.Print.*;  public class Apply {    public static <T, S extends Iterable<? extends T>>    void apply(S seq, Method f, Object... args) {      try {        for(T t: seq)          f.invoke(t, args);      } catch(Exception e) {        // Failures are programmer errors        throw new RuntimeException(e);      }    }  }  class Shape {    public void rotate() { print(this + " rotate"); }    public void resize(int newSize) {      print(this + " resize " + newSize);    }  }  class Square extends Shape {}  class FilledList<T> extends ArrayList<T> {    public FilledList(Class<? extends T> type, int size) {      try {        for(int i = 0; i < size; i++)          // Assumes default constructor:          add(type.newInstance());      } catch(Exception e) {        throw new RuntimeException(e);      }    }  }  class ApplyTest {    public static void main(String[] args) throws Exception {      List<Shape> shapes = new ArrayList<Shape>();      for(int i = 0; i < 10; i++)        shapes.add(new Shape());      Apply.apply(shapes, Shape.class.getMethod("rotate"));      Apply.apply(shapes,        Shape.class.getMethod("resize", int.class), 5);      List<Square> squares = new ArrayList<Square>();      for(int i = 0; i < 10; i++)        squares.add(new Square());      Apply.apply(squares, Shape.class.getMethod("rotate"));      Apply.apply(squares,        Shape.class.getMethod("resize", int.class), 5);        Apply.apply(new FilledList<Shape>(Shape.class, 10),        Shape.class.getMethod("rotate"));      Apply.apply(new FilledList<Shape>(Square.class, 10),        Shape.class.getMethod("rotate"));        SimpleQueue<Shape> shapeQ = new SimpleQueue<Shape>();      for(int i = 0; i < 5; i++) {        shapeQ.add(new Shape());        shapeQ.add(new Square());      }      Apply.apply(shapeQ, Shape.class.getMethod("rotate"));    }  } /* (Execute to see output) *///:~

apple(0??????????Iterable????????List?????Collection??
????????

import java.util.*;    public class SimpleQueue<T> implements Iterable<T> {    private LinkedList<T> storage = new LinkedList<T>();    public void add(T t) { storage.offer(t); }    public T get() { return storage.poll(); }    public Iterator<T> iterator() {      return storage.iterator();    }  } ///:~

15.17.3 ????????????

??Iterable?????????????????????????????????

import java.util.*;    // Doesn't work with "anything that has an add()." There is  // no "Addable" interface so we are narrowed to using a  // Collection. We cannot generalize using generics in  // this case.  public class Fill {    public static <T> void fill(Collection<T> collection,    Class<? extends T> classToken, int size) {      for(int i = 0; i < size; i++)        // Assumes default constructor:        try {          collection.add(classToken.newInstance());        } catch(Exception e) {          throw new RuntimeException(e);        }    }  }    class Contract {    private static long counter = 0;    private final long id = counter++;    public String toString() {      return getClass().getName() + " " + id;    }  }    class TitleTransfer extends Contract {}    class FillTest {    public static void main(String[] args) {      List<Contract> contracts = new ArrayList<Contract>();      Fill.fill(contracts, Contract.class, 3);      Fill.fill(contracts, TitleTransfer.class, 2);      for(Contract c: contracts)        System.out.println(c);      SimpleQueue<Contract> contractQueue =        new SimpleQueue<Contract>();      // Won't work. fill() is not generic enough:      // Fill.fill(contractQueue, Contract.class, 3);    }  } /* Output:  Contract 0  Contract 1  Contract 2  TitleTransfer 3  TitleTransfer 4  *///:~

15.17.4 ????????????

????????????????????????????????????????????????????????????????????????????????????????????????????????????????
??????????????????????????

import coffee.*;  import java.util.*;  import net.mindview.util.*;  import static net.mindview.util.Print.*;    interface Addable<T> { void add(T t); }    public class Fill2 {    // Classtoken version:    public static <T> void fill(Addable<T> addable,    Class<? extends T> classToken, int size) {      for(int i = 0; i < size; i++)        try {          addable.add(classToken.newInstance());        } catch(Exception e) {          throw new RuntimeException(e);        }    }    // Generator version:    public static <T> void fill(Addable<T> addable,    Generator<T> generator, int size) {      for(int i = 0; i < size; i++)        addable.add(generator.next());    }  }    // To adapt a base type, you must use composition.  // Make any Collection Addable using composition:  class AddableCollectionAdapter<T> implements Addable<T> {    private Collection<T> c;    public AddableCollectionAdapter(Collection<T> c) {      this.c = c;    }    public void add(T item) { c.add(item); }  }    // A Helper to capture the type automatically:  class Adapter {    public static <T>    Addable<T> collectionAdapter(Collection<T> c) {      return new AddableCollectionAdapter<T>(c);    }  }    // To adapt a specific type, you can use inheritance.  // Make a SimpleQueue Addable using inheritance:  class AddableSimpleQueue<T>  extends SimpleQueue<T> implements Addable<T> {    public void add(T item) { super.add(item); }  }    class Fill2Test {    public static void main(String[] args) {      // Adapt a Collection:      List<Coffee> carrier = new ArrayList<Coffee>();      Fill2.fill(        new AddableCollectionAdapter<Coffee>(carrier),        Coffee.class, 3);      // Helper method captures the type:      Fill2.fill(Adapter.collectionAdapter(carrier),        Latte.class, 2);      for(Coffee c: carrier)        print(c);      print("----------------------");      // Use an adapted class:      AddableSimpleQueue<Coffee> coffeeQueue =        new AddableSimpleQueue<Coffee>();      Fill2.fill(coffeeQueue, Mocha.class, 4);      Fill2.fill(coffeeQueue, Latte.class, 1);      for(Coffee c: coffeeQueue)        print(c);    }  } /* Output:  Coffee 0  Coffee 1  Coffee 2  Latte 3  Latte 4  ----------------------  Mocha 5  Mocha 6  Mocha 7  Mocha 8  Latte 9  *///:~

15.18 ?????????

??????????????????????????????????????????????
?????????????????????????????????????????????????
???????????????????????????????????????????????????????

//: generics/Functional.java  import java.math.*;  import java.util.concurrent.atomic.*;  import java.util.*;  import static net.mindview.util.Print.*;    // Different types of function objects:  interface Combiner<T> { T combine(T x, T y); }  interface UnaryFunction<R,T> { R function(T x); }  interface Collector<T> extends UnaryFunction<T,T> {    T result(); // Extract result of collecting parameter  }  interface UnaryPredicate<T> { boolean test(T x); }    public class Functional {    // Calls the Combiner object on each element to combine    // it with a running result, which is finally returned:    public static <T> T    reduce(Iterable<T> seq, Combiner<T> combiner) {      Iterator<T> it = seq.iterator();      if(it.hasNext()) {        T result = it.next();        while(it.hasNext())          result = combiner.combine(result, it.next());        return result;      }      // If seq is the empty list:      return null; // Or throw exception    }    // Take a function object and call it on each object in    // the list, ignoring the return value. The function    // object may act as a collecting parameter, so it is    // returned at the end.    public static <T> Collector<T>    forEach(Iterable<T> seq, Collector<T> func) {      for(T t : seq)        func.function(t);      return func;    }    // Creates a list of results by calling a    // function object for each object in the list:    public static <R,T> List<R>    transform(Iterable<T> seq, UnaryFunction<R,T> func) {      List<R> result = new ArrayList<R>();      for(T t : seq)        result.add(func.function(t));      return result;    }    // Applies a unary predicate to each item in a sequence,    // and returns a list of items that produced "true":    public static <T> List<T>    filter(Iterable<T> seq, UnaryPredicate<T> pred) {      List<T> result = new ArrayList<T>();      for(T t : seq)        if(pred.test(t))          result.add(t);      return result;    }    // To use the above generic methods, we need to create    // function objects to adapt to our particular needs:    static class IntegerAdder implements Combiner<Integer> {      public Integer combine(Integer x, Integer y) {        return x + y;      }    }    static class    IntegerSubtracter implements Combiner<Integer> {      public Integer combine(Integer x, Integer y) {        return x - y;      }    }    static class    BigDecimalAdder implements Combiner<BigDecimal> {      public BigDecimal combine(BigDecimal x, BigDecimal y) {        return x.add(y);      }    }    static class    BigIntegerAdder implements Combiner<BigInteger> {      public BigInteger combine(BigInteger x, BigInteger y) {        return x.add(y);      }    }    static class    AtomicLongAdder implements Combiner<AtomicLong> {      public AtomicLong combine(AtomicLong x, AtomicLong y) {        // Not clear whether this is meaningful:        return new AtomicLong(x.addAndGet(y.get()));      }    }    // We can even make a UnaryFunction with an "ulp"    // (Units in the last place):    static class BigDecimalUlp    implements UnaryFunction<BigDecimal,BigDecimal> {      public BigDecimal function(BigDecimal x) {        return x.ulp();      }    }    static class GreaterThan<T extends Comparable<T>>    implements UnaryPredicate<T> {      private T bound;      public GreaterThan(T bound) { this.bound = bound; }      public boolean test(T x) {        return x.compareTo(bound) > 0;      }    }    static class MultiplyingIntegerCollector    implements Collector<Integer> {      private Integer val = 1;      public Integer function(Integer x) {        val *= x;        return val;      }      public Integer result() { return val; }    }    public static void main(String[] args) {      // Generics, varargs & boxing working together:      List<Integer> li = Arrays.asList(1, 2, 3, 4, 5, 6, 7);      Integer result = reduce(li, new IntegerAdder());      print(result);        result = reduce(li, new IntegerSubtracter());      print(result);        print(filter(li, new GreaterThan<Integer>(4)));        print(forEach(li,        new MultiplyingIntegerCollector()).result());        print(forEach(filter(li, new GreaterThan<Integer>(4)),        new MultiplyingIntegerCollector()).result());        MathContext mc = new MathContext(7);      List<BigDecimal> lbd = Arrays.asList(        new BigDecimal(1.1, mc), new BigDecimal(2.2, mc),        new BigDecimal(3.3, mc), new BigDecimal(4.4, mc));      BigDecimal rbd = reduce(lbd, new BigDecimalAdder());      print(rbd);        print(filter(lbd,        new GreaterThan<BigDecimal>(new BigDecimal(3))));        // Use the prime-generation facility of BigInteger:      List<BigInteger> lbi = new ArrayList<BigInteger>();      BigInteger bi = BigInteger.valueOf(11);      for(int i = 0; i < 11; i++) {        lbi.add(bi);        bi = bi.nextProbablePrime();      }      print(lbi);        BigInteger rbi = reduce(lbi, new BigIntegerAdder());      print(rbi);      // The sum of this list of primes is also prime:      print(rbi.isProbablePrime(5));        List<AtomicLong> lal = Arrays.asList(        new AtomicLong(11), new AtomicLong(47),        new AtomicLong(74), new AtomicLong(133));      AtomicLong ral = reduce(lal, new AtomicLongAdder());      print(ral);        print(transform(lbd,new BigDecimalUlp()));    }  } /* Output:  28  -26  [5, 6, 7]  5040  210  11.000000  [3.300000, 4.400000]  [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]  311  true  265  [0.000001, 0.000001, 0.000001, 0.000001]  *///:~