练习1:
// Use Holder3 with the typeinfo.pets library to show that a Holder3 that is
// specified to hold a base type can also hold a derived type.
import typeinfo.pets.*;
class Holder{
private T a;
Holder(T a){this.a=a;}
void f(){System.out.println(a);}
void set(T a){this.a=a;}
}
public class Ja15_1{
public static void main(String[] args){
Holder h=new Holder(new Pet("fsdf"));
h.f();
h.set(new Dog("dogg"));
h.f();
h.set(new Cat("catt"));
h.f();
}
}
// Use Holder3 with the typeinfo.pets library to show that a Holder3 that is
// specified to hold a base type can also hold a derived type.
import typeinfo.pets.*;
class Holder{
private T a;
Holder(T a){this.a=a;}
void f(){System.out.println(a);}
void set(T a){this.a=a;}
}
public class Ja15_1{
public static void main(String[] args){
Holder h=new Holder(new Pet("fsdf"));
h.f();
h.set(new Dog("dogg"));
h.f();
h.set(new Cat("catt"));
h.f();
}
}
练习2:
/* Create a holder class that holds three objects of the same type along
* with the methods to store and fetch those objects and a constructor to
* initialize all three.
*/
import static net.mindview.util.Print.*;
import typeinfo.pets.*;
public class Ja15_2{
private T a;
private T b;
private T c;
Ja15_2(){a=null;b=null;c=null;}
void setA(T a){this.a=a;}
void setB(T b){this.b=b;}
void setC(T c){this.c=c;}
void getA(){print( a);}
void getB(){print( b);}
void getC(){print( c);}
public static void main(String[] args){
Ja15_2 ja=new Ja15_2();
ja.setA(new Cat("cat"));
ja.setB(new Dog("dog"));
ja.setC(new Pug("pug"));
ja.getA();
ja.getB();
ja.getC();
}
}
练习3:
// Create and test a SixTuple generic.
import net.mindview.util.*;
import typeinfo.pets.*;
import static net.mindview.util.Print.*;
public class Ja15_3 extends FiveTuple{
public final F sixth;
Ja15_3(A a, B b, C c, D d, E e,F f){
super(a,b,c,d,e);
sixth=f;
}
public String toString(){return "(" + first + ", " + second + ", " +third + ", " + fourth + ", " + fifth +", " +sixth+")";}
public static void main(String[] args){
Ja15_3 ja=new Ja15_3(new Cat(),new Dog(),new Pug(),new Pet(),"das",56);
print(ja);
}
}
练习4:
// 'Generify' innerclasses/Ja15_4.java.
interface Selector {
boolean end();
TT current();
void next();
}
public class Ja15_4 {
private TT[] items;
private int next = 0;
public Ja15_4(TT[] mm) { items = mm; }
public void add(TT x) {
if(next < items.length)
items[next++] = x;
}
private class Ja15_4Selector implements Selector {
private int i = 0;
public boolean end() { return i == items.length; }
public TT current() { return items[i]; }
public void next() { if(i < items.length) i++; }
}
public Selector selector() {
return new Ja15_4Selector();
}
public static void main(String[] args) {
Ja15_4 sequence = new Ja15_4(new String[10]);
for(int i = 0; i < 10; i++)
sequence.add(Integer.toString(i));
Selector selector = sequence.selector();
while(!selector.end()) {
System.out.print(selector.current() + " ");
selector.next();
}
}
}
练习5:
public class Ja15_5 {
private class Node {
T item;
Node next;
Node() { item = null; next = null; }
Node(T item, Node next) {
this.item = item;
this.next = next;
}
boolean end() { return item == null && next == null; }
}
private Node top = new Node(); // End sentinel
public void push(T item) {
top = new Node(item, top);
}
public T pop() {
T result = top.item;
if(!top.end())
top = top.next;
return result;
}
public static void main(String[] args) {
Ja15_5 lss = new Ja15_5();
for(String s : "Phasers on stun!".split(" "))
lss.push(s);
String s;
while((s = lss.pop()) != null)
System.out.println(s);
}
}
练习6:
// Use RandomList with two more types in addition to the one shown in main().
import java.util.*;
public class Ja15_6 {
private ArrayList storage = new ArrayList();
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) {
Ja15_6 rs = new Ja15_6();
for(Integer s: Arrays.asList(4,6,87,211,76))//形成数组方法
rs.add(s);
for(int i = 0; i < 11; i++)
System.out.print(rs.select() + " ");
}
}
练习7:
// Use composition instead of inheritance to adapt Fibonacci
// to make it interable.
import java.util.*;
import net.mindview.util.*;
import generics.*;
public class Ja15_7 implements Generator,Iterable {
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);
}
private int size;
public Ja15_7(){}
public Ja15_7(int size){this.size=size;}
public Iterator iterator(){
return new Iterator(){
public boolean hasNext(){return size>0;}
public Integer next(){size--;return Ja15_7.this.next();}
public void remove(){throw new RuntimeException();}
};
}
public static void main(String[] args) {
Ja15_7 gen = new Ja15_7();
for(int i = 0; i < 18; i++)
System.out.print(gen.next() + " ");
for(Integer in:new Ja15_7(5))
System.out.println(in);
}
}
练习8:
/* Following the form of the Coffee example, create a hierarchy of StoryCharacter(s) from
* your favorite movie, dividing them into GoodGuy(s) and BadGuy(s). Create a generator
* for StoryCharacter(s), following the form of CoffeeGenerator.*/
import java.util.*;
interface Generator{
public T next();
}
class Guy{
private static int count=0;
private final int id=count++;
public String toSting(){return getClass().getSimpleName()+" "+id;}
}
class GoodGuy extends Guy{}
class BadGuy extends Guy{}
public class Ja15_8 implements Generator{
private static Class[] types={GoodGuy.class,BadGuy.class};
Random rand=new Random(55);
public Guy next(){
try{
return (Guy)types[rand.nextInt(types.length)].newInstance();
}catch(Exception e){
throw new RuntimeException(e);
}
}
public static void main(String[] args){
Ja15_8 gen=new Ja15_8();
for(int i=0;i<3;i++)System.out.println(gen.next());
}
}
练习9:
// Modify GenericMethods so that f() accepts three arguments, all
// of which are of a different parameterized type.
public class Ja15_9 {
public void f(T x,U u,V v) {
System.out.println(x.getClass().getName());
System.out.println(u.getClass().getName());
System.out.println(v.getClass().getName());
}
public static void main(String[] args) {
Ja15_9 gm = new Ja15_9();
gm.f(gm,1.0f,'c');
}
}
练习10:
// Modify the previous exercise so that one of f()'s arguments
// is non-parameterized.
public class Ja15_10{
public void f(T x,U u,V v,Integer i) {
System.out.println(x.getClass().getName());
System.out.println(u.getClass().getName());
System.out.println(v.getClass().getName());
System.out.println(i.getClass().getName());
}
public static void main(String[] args) {
Ja15_10 gm = new Ja15_10();
gm.f(1.0f,'c',gm,1);
}
}
练习11:
// Test New.java by creating your own classes and ensuring that
// New will work properly with them.
import java.util.*;
public class Ja15_11 {
public static Map map() {
return new HashMap();
}
public static List list() {
return new ArrayList();
}
public static LinkedList lList() {
return new LinkedList();
}
public static Set set() {
return new HashSet();
}
public static Queue queue() {
return new LinkedList();
}
// Examples:
public static void main(String[] args) {
Map> sls = Ja15_11.map();
List ls = Ja15_11.list();
LinkedList lls = Ja15_11.lList();
Set ss = Ja15_11.set();
Queue qs = Ja15_11.queue();
}
}
练习12:
// Repeat the previous exercise using explicit type specification.
import java.util.*;
public class Ja15_12 {
public static Map map() {
return new HashMap();
}
public static List list() {
return new ArrayList();
}
public static LinkedList lList() {
return new LinkedList();
}
public static Set set() {
return new HashSet();
}
public static Queue queue() {
return new LinkedList();
}
// Examples:
public static void f(Map> a){}
public static void main(String[] args) {
f(Ja15_12.>map());
Map> sls = Ja15_11.map();
List ls = Ja15_11.list();
LinkedList lls = Ja15_11.lList();
Set ss = Ja15_11.set();
Queue qs = Ja15_11.queue();
}
}
练习13:
/* Overload the fill() method so that the arguments and return types are
* the specific subtypes of Collection: List, Queue and Set. This way, you
* don't lose the type of container. Can you overload to distinguish between
* List and LinkedList?
*/
import generics.coffee.*;
import java.util.*;
import net.mindview.util.*;
public class Ja15_13 {
/*public static Collection
fill(Collection coll, Generator gen, int n) {
for(int i = 0; i < n; i++)
coll.add(gen.next());
return coll;
}*/
public static Set fill(Set coll,Generator gen,int n){
for(int i = 0; i < n; i++)
coll.add(gen.next());
return coll;
}
public static List fill(List coll,Generator gen,int n){
for(int i = 0; i < n; i++)
coll.add(gen.next());
System.out.println("List Only");//可以区分List和LinkedList
return coll;
}
public static LinkedList fill(LinkedList coll,Generator gen,int n){
for(int i = 0; i < n; i++)
coll.add(gen.next());
System.out.println("LinkedList");
return coll;
}
public static void main(String[] args) {
/*Collection coffee = fill(
new ArrayList(), new CoffeeGenerator(), 4);
for(Coffee c : coffee)
System.out.println(c);*/
Collection c1 = fill(
new ArrayList(), new CoffeeGenerator(), 4);
for(Coffee c : c1)
System.out.println(c);
Collection c2 = fill(
new LinkedList(), new CoffeeGenerator(), 4);
for(Coffee c : c2)
System.out.println(c);
/*Collection fnumbers = fill(
new ArrayList(), new Fibonacci(), 12);
for(int i : fnumbers)
System.out.print(i + ", ");*/
}
}
练习14:
/* Modify BasicGeneratorDemo.java to use the explicit form of creation for the
* Generator (that is, use the explict constructor instead of the generic
* create() method).
*/
import net.mindview.util.*;
import generics.*;
public class Ja15_14 {
public static void main(String[] args) {
BasicGenerator ge=new BasicGenerator(CountedObject.class);
//Generator gen =
//BasicGenerator.create(CountedObject.class);
for(int i = 0; i < 5; i++)
System.out.println(ge.next());
}
}
练习15:
/* ... if you were to try to capture the result of f2() into a
* paramterized TwoTuple, the compiler would issue a warning.
* Verify the previous statement.
*/
import net.mindview.util.*;
import static net.mindview.util.Tuple.*;
import typeinfo.pets.*;
public class Ja15_15 {
static TwoTuple f() {
return tuple("hi", 47);
}
static TwoTuple f2() { return tuple("hi", 47); }
/*static ThreeTuple g() {
return tuple(new Pug(), "hi", 47);
}*/
static
FourTuple h() {
return tuple(new Dog(), new Pug(), "hi", 47);
}
static
FiveTuple k() {
return tuple(new Dog(), new Pug(),
"hi", 47, 11.1);
}
public static void main(String[] args) {
TwoTuple ttsi = f();
/*编译器警告未经审查*/
TwoTuple ttsi2 = f2();
System.out.println(ttsi);
System.out.println(f2());
//System.out.println(g());
System.out.println(h());
System.out.println(k());
}
}
练习16:
// Add a SixTuple to Tuple.java and test it in TupleTest2.java.
import net.mindview.util.*;
import static net.mindview.util.Tuple.*;
import typeinfo.pets.*;
public class Ja15_16 {
static TwoTuple f() {
return tuple("hi", 47);
}
static TwoTuple f2() { return tuple("hi", 47); }
/*static ThreeTuple g() {
return tuple(new Pug(), "hi", 47);
}*/
static
FourTuple h() {
return tuple(new Dog(), new Pug(), "hi", 47);
}
static
FiveTuple k() {
return tuple(new Dog(), new Pug(),
"hi", 47, 11.1);
}
static SixTuple j(){
return tuple(new Dog(), new Pug(), "hi", 47, 11.1,new Cat());
}
public static void main(String[] args) {
TwoTuple ttsi = f();
System.out.println(ttsi);
System.out.println(f2());
//System.out.println(g());
System.out.println(h());
System.out.println(k());
System.out.println(j());
}
}
练习17:
???
练习18:
// Following the form of BankTeller.java, create an example where
// BigFish eat LittleFish in the ocean.
import static net.mindview.util.Print.*;
class Generator{
}
class BigFish{
private BigFish(){}
public static Generator generator(){
return new Generator(){
public BigFish next(){return new BigFish();}
public String toString(){
return "BigFish";
}
};
}
}
class LittleFish{
private LittleFish(){}
public static Generator generator=new Generator(){
public LittleFish next(){
return new LittleFish();
}
public String toString(){
return "LittleFish";
}
};
}
public class Ja15_18{
public static void main(String[] args){
print(BigFish.generator());
print(LittleFish.generator);
}
}
练习19:
// Following the form of Store.java, build a model of a containerized
// cargo ship.
import static net.mindview.util.Print.*;
import java.util.*;
import net.mindview.util.*;
import generics.*;
class A{
private static int count=0;
private final int id=count++;
public String toString(){return "A"+id;}
public static Generator generator=new Generator(){
public A next(){
return new A();
}
};
}
class B extends ArrayList{
public B(int a){
//for(int i=0;i{
public C(int b,int a){
for(int i=0;i{
public Ja15_19(int c,int b,int a){
for(int i=0;i
PS:一定要和generators放在一个文件夹内??
练习20:
/* Create an interface with two methods, and a class that implements that interface
* and adds another method. In another class, create a generic method with an
* argument type that is bounded by the interface, and show that the methods in the
* interface are callable inside this generic method. In main(), pass an instance of
* the implementing class to the generic method.
*/
import static net.mindview.util.Print.*;
interface A{
public void f();
public void h();
}
class B implements A{
public void f(){print("f");}
public void h(){print("h");}
public void g(){print("g");}
}
class C{
public void j(T t){t.f();t.h();}//t.g();}
}
public class Ja15_20{
public static void main(String[] args){
C c=new C();
B b=new B();
c.j(b);
}
}
练习21:
/* Modify Ja15_21.java by adding a Map>,
* a method addType(String typename, Class> kind), and a
* method createNew(String typename). creatNew() will either
* produce a new instance of the class associated with its
* argument string, or produce an error message.
*/
import java.util.*;
import static net.mindview.util.Print.*;
class Building {}
class House extends Building {}
public class Ja15_21 {
Class kind;
public Ja15_21(Class kind) {
this.kind = kind;
}
Map> mm=new LinkedHashMap>();
public void addType(String typename, Class> kind) {
mm.put(typename, kind);
}
public void createNew(String typename){
try{
print(mm.get(typename).newInstance());
}catch(Exception e){
throw new RuntimeException(e);
}
}
public boolean f(Object arg) {
return kind.isInstance(arg);
}
public static void main(String[] args) {
Ja15_21 ctt1 =
new Ja15_21(Building.class);
System.out.println(ctt1.f(new Building()));
System.out.println(ctt1.f(new House()));
Ja15_21 ctt2 =
new Ja15_21(House.class);
System.out.println(ctt2.f(new Building()));
System.out.println(ctt2.f(new House()));
ctt1.addType("aa",Building.class);
ctt1.createNew("aa");
}
}
练习22:
/* Use a type tag along with reflection to create a method that uses the
* argument version of newInstance() to create an object of a class with
* a constructor that has arguments.
*/
import java.util.*;
import static net.mindview.util.Print.*;
class A{
public A(Integer i){
print(i);
}
public A(){}
public String toString(){return ("Congratulations!!");}
}
class B{
T x;
public B(Class> kind,Integer i,String typename){
try{
print(Class.forName(typename).getDeclaredConstructor(i.getClass()).newInstance(i));
//x=kind.newInstance(i);
print("x "+i);
}catch(Exception e){
throw new RuntimeException(e);
}
}
}
public class Ja15_22{
public static void main(String[] args){
B b=new B(A.class,2,"A");
}
}
PS: i.getClass()只能应用于Integer之类,不能是int!练习23:
// Modify FactoryConstraint.java so that create() takes an argument.
import static net.mindview.util.Print.*;
interface FactoryI {
T create(Integer i);
}
class Foo2 {
private T x;
public > Foo2(F factory,Integer i) {
x = factory.create(i);
}
// ...
}
class IntegerFactory implements FactoryI {
public Integer create(Integer i) {
print(i);
return new Integer(i);
}
}
class Widget {
public Widget(Integer i){print(i);}
public static class Factory implements FactoryI {
public Widget create(Integer i) {
return new Widget(i);
}
}
}
public class Ja15_23 {
public static void main(String[] args) {
new Foo2(new IntegerFactory(),4);
new Foo2(new Widget.Factory(),5);
}
}
练习24:
// Modify Exercise 21 so that factory objects are held in the Map instead of Class>.
import java.util.*;
import static net.mindview.util.Print.*;
class Building {
}
class House extends Building {}
interface Factory{
T create();
}
class BuildingFactory implements Factory{
public Building create(){return new Building();}
}
class HouseFactory implements Factory{
public House create(){return new House();}
}
public class Ja15_24 {
Class kind;
public Ja15_24(Class kind) {
this.kind = kind;
}
Map mm=new LinkedHashMap();
public void addType(String typename, Factory kind) {
mm.put(typename, kind);
}
public void createNew(String typename){
try{
print(mm.get(typename).create());
}catch(Exception e){
throw new RuntimeException(e);
}
}
public boolean f(Object arg) {
return kind.isInstance(arg);
}
public static void main(String[] args) {
Ja15_24 ctt1 =
new Ja15_24(Building.class);
System.out.println(ctt1.f(new Building()));
System.out.println(ctt1.f(new House()));
Ja15_24 ctt2 =
new Ja15_24(House.class);
System.out.println(ctt2.f(new Building()));
System.out.println(ctt2.f(new House()));
ctt1.addType("aa",new HouseFactory());
ctt1.createNew("aa");
}
}
练习25:
/* Create two interfaces and a class that implements both. Create two
* generic methods, one whose argument parameter is bounded by the first
* interface and one whose argument parameter is bounded by the second
* interface. Create an instance of the class that implements both
* interfaces, and show that it can be used with both generic methods.
*/
import static net.mindview.util.Print.*;
interface A{void a();}
interface B{void b();}
class C implements A,B{
public void a(){print("aa");}
public void b(){print("bb");}
void f(T a){a.a();} //A和B相当于是上边界,Object类在这个上边界之上
void g(T b){b.b();}
void m(T m){print("T m");}
}
class D extends C{}
public class Ja15_25{
public static void main(String[] args){
C c=new C();
c.f(new C());
c.g(new C());
c.f(new D());
c.m(new Object());
}
}
练习26:
// Demonstrate array covariance using Numbers and Integers.
import static net.mindview.util.Print.*;
public class Ja15_26{
public static void main(String[] args){
Number[] nu=new Number[3];
nu[0]=new Integer(0);//OK
nu[1]=new Double(3.3);//OK
nu[0]=new Double(3.6);//OK??
print(nu[0]);
Number[] in=new Integer[3];//这就是协变类型
//in[0]=new Number(8); //abstract class
in[0]=new Integer(0);
System.out.print(in[0].getClass().getSimpleName());
//in[1]=new Double(2.2);//Runtime ArrayStoreException
}
}
练习27:
// Show that covariancd doesn't work with Lists using Numbers and
// Integers, then introduce wildcards.
import java.util.*;
public class Ja15_27 {
public static void main(String[] args) {
// compile error: incompatible types:
// List lnum = new ArrayList();
List extends Number> nlist = new ArrayList();
// compile error: can't add Integer:
// nlist.add(new Integer(0));
nlist.add(null); // can add null
Number x = nlist.get(0); // can get Number (null)
System.out.println(nlist);
}
}
练习28:
/* Create a generic class Generic1 with a single method that takes an argument
* of type T. Create a second generic class Generic2 with a single method that
* returns an argument of type T. Write a generic method with a contravariant
* argument of the first generic class that calls its method. Write a second generic
* method with a covariant argument of the second class that calls its method. Test
* using the typeinfo.pets library.
*/
import typeinfo.pets.*;
import static net.mindview.util.Print.*;
public class Ja15_28{
class Generic1{
T t;
void f1(T t){}
}
class Generic2{
T t;
T f2(){return t;}
}
void contra(Generic1 super T> g,T t){
g.f1(t);
}
void co(Generic2 extends T> g2){
print(g2.f2());
}
public static void main(String[] args){
Ja15_28 j=new Ja15_28();
j.contra(j.new Generic1(),new Dog("dogy"));
j.co(j.new Generic2());
}
}
练习29:
/* Create a generic method that takes as an argument a Holder>.
* Determine what methods you can and can't call for the Holder and for
* the List. Repeat for an argument of List>.
*/
import generics.*;
import static net.mindview.util.Print.*;
import java.util.*;
class Fruit{}
class Apple extends Fruit{}
class Orange extends Fruit{}
class Holder {
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 = new Holder(new Apple());
Apple d = Apple.get();
Apple.set(d);
// Holder Fruit = Apple; // Cannot upcast
Holder extends Fruit> fruit = Apple; // OK
Fruit p = fruit.get();
d = (Apple)fruit.get(); // Returns 'Object'-->'Apple'?
System.out.println(d.getClass().getSimpleName());
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
}
}
public class Ja15_29{
static void f(Holder> h){
h.set(new ArrayList());
print(h.get().getClass().getSimpleName());
}
public static void main(String[] args){
Holder> h=new Holder>();
f(h);
Holder> h2=new Holder>();
f(h2);
}
}
练习30:
// Create a Holder for each of the primitive wrapper types, and show that
// autoboxing and autounboxing works for the set() and get() methods of
// each instance.
import static net.mindview.util.Print.*;
public class Ja15_30{
public static void main(String[] args){
Holder h=new Holder();
int i=4;
h.set(i);
print(h.get().getClass());
}
}
练习31:
// Remove all generics from MultipleInterfaceVariants.java and modify
// the code so that the example compiles.
interface Payable {}
class Employee implements Payable {}
class Hourly extends Employee implements Payable {} ///:~
练习32:
/*
* Verify that FixedSizeStack in GenericCast.java generates exceptions
* if you try to go out of its bounds. Does this mean that bounds-checking
* code is not required?
*/
//: generics/GenericCast.java
class FixedSizeStack {
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]; }
}
public class Ja15_32 {
public static final int SIZE = 10;
public static void main(String[] args) {
FixedSizeStack strings =
new FixedSizeStack(SIZE);
for(String s : "A B C D E F G H I J".split(" "))
strings.push(s);
//RuntimeException
//strings.push("fsd");
for(int i = 0; i < SIZE; i++) {
String s = strings.pop();
System.out.print(s + " ");
}
}
}
练习33:
// Repair GenericCast.java using an ArrayList.
import java.util.*;
class FixedSizeStack {
private int index = 0;
private List storage=new ArrayList();
public FixedSizeStack() {
}
public void push(T item) { storage.add(item);}
@SuppressWarnings("unchecked")
public int count(){return storage.size();}
public T pop() { return (T)storage.remove(storage.size()-1); }
}
public class Ja15_33 {
public static void main(String[] args) {
FixedSizeStack strings =
new FixedSizeStack();
for(String s : "A B C D E F G H I J".split(" "))
strings.push(s);
int count = strings.count();
for(int i=0;i
练习34:
/* Create a self-bounded generic type that contains an abstract method
* that takes an argument of the generic type parameter and produces a
* return value of the generic type parameter. In a non-abstract method
* of the class, call the abstract method and return its result. Inherit
* from the self-bounded type and test the resulting class.
*/
abstract class A>{
abstract T f(T a);
T h(T t){return f(t);}
}
class B extends A{
B f(B b){return b;}
}
public class Ja15_34{
public static void main(String[] args){
B m=new B();
m.h(new B());
}
}
练习35:
// Modify CheckedList.java so that it uses the Coffee classes defined
import java.util.Collections.*;
import java.util.*;
import generics.coffee.*;
public class Ja15_35{
public static void main(String[] args){
Set la=Collections.checkedSet(new HashSet(),Latte.class);
la.add(new Latte());
//la.add(new Coffee());
}
}
练习36:
// Add a second parameterized exception to the Processor class and
// demonstrate that the exceptions can vary independently.
import java.util.*;
interface Processor {
void process(List resultCollector) throws E,F;
}
class ProcessRunner
extends ArrayList> {
List processAll() throws E,F {
List resultCollector = new ArrayList();
for(Processor processor : this)
processor.process(resultCollector);
return resultCollector;
}
}
class Failure1 extends Exception {}
class Failure3 extends Exception {}
class Processor1 implements Processor {
static int count = 3;
public void
process(List resultCollector) throws Failure1,Failure3 {
if(count-- > 1)
resultCollector.add("Hep!");
else
resultCollector.add("Ho!");
if(count < 0&&count>-1)
{throw new Failure1();}
if(count<-1){throw new Failure3();}
}
}
class Failure2 extends Exception {}
class Failure4 extends Exception {}
class Processor2 implements Processor {
static int count = 2;
public void
process(List resultCollector) throws Failure2,Failure4 {
if(count-- == 0)
resultCollector.add(47);
else {
resultCollector.add(11);
}
if(count < 0&&count>-1)
{throw new Failure2();}
if(count<-1){throw new Failure4();}
}
}
public class Ja15_36{
public static void main(String[] args) {
ProcessRunner runner =
new ProcessRunner();
for(int i = 0; i < 3; i++)
runner.add(new Processor1());
try {
System.out.println(runner.processAll());
} catch(Failure1 e) {
System.out.println(e);
}catch(Failure3 e){}
ProcessRunner runner2 =
new ProcessRunner();
for(int i = 0; i < 3; i++)
runner2.add(new Processor2());
try {
System.out.println(runner2.processAll());
} catch(Failure2 e) {
System.out.println(e);
}catch(Failure4 e){}
}
}
练习37:
练习38:
// generics/CoffeeDecoration38.java
// TIJ4 Chapter Generics, Exercise 38, page 719
// Create a simple Decorator system by starting with basic coffee, then
// providing decorators of steamed milk, foam, chocolate, caramel and
// whipped cream.
import static net.mindview.util.Print.*;
import generics.coffee.*;
import java.util.*;
class BasicCoffee {
private static long counter = 0;
private final long id = counter++;
private String value;
public void set(String val) { value = val; }
public String get() { return value; }
public String toString() {
return getClass().getSimpleName() + " " + id;
}
}
class Decorator extends BasicCoffee {
protected BasicCoffee basicCoffee;
public Decorator(BasicCoffee basicCoffee) {
this.basicCoffee = basicCoffee;
}
public void set(String val) { basicCoffee.set(val); }
public String get() { return basicCoffee.get(); }
}
class SteamedMilk extends Decorator {
private final String steamedMilk = "steamedMilk";
public SteamedMilk(BasicCoffee basicCoffee) {
super(basicCoffee);
}
public String getSteamedMilk() { return steamedMilk; }
}
class Foam extends Decorator {
private final String foam = "foam";
public Foam(BasicCoffee basicCoffee) {
super(basicCoffee);
}
public String getFoam() { return foam; }
}
class Chocolate extends Decorator {
private final String chocolate = "chocolate";
public Chocolate(BasicCoffee basicCoffee) {
super(basicCoffee);
}
public String getChocolate() { return chocolate; }
}
class Caramel extends Decorator {
private final String caramel = "caramel";
public Caramel(BasicCoffee basicCoffee) {
super(basicCoffee);
}
public String getCaramel() { return caramel; }
}
class WhippedCream extends Decorator {
private final String whippedCream = "whippedCream";
public WhippedCream(BasicCoffee basicCoffee) {
super(basicCoffee);
}
public String getWhippedCream() { return whippedCream; }
}
public class Ja15_38{
public static void main(String[] args) {
SteamedMilk sm = new SteamedMilk(new BasicCoffee());
SteamedMilk sm2 = new SteamedMilk(
new Foam(new BasicCoffee()));
Chocolate c = new Chocolate(new BasicCoffee());
WhippedCream wc = new WhippedCream(new Caramel(
new Chocolate(new Foam(new SteamedMilk(
new BasicCoffee())))));
print(wc.getCaramel());
}
}
练习39:
//: generics/DynamicProxyMixin.java
import java.lang.reflect.*;
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Tuple.*;
class MixinProxy implements InvocationHandler {
Map delegatesByMethod;
public MixinProxy(TwoTuple
PS:无法通过安全检查?(哪怕用了@SuppressWarnings)
练习40:
// Add a speak() method to all the pets in tyepinfo.pets. Modify Apply.java to call the speak
// method for a heterogeneous collection of Pet.
//: generics/Apply.java
// {main: ApplyTest}
import java.lang.reflect.*;
import java.util.*;
import static net.mindview.util.Print.*;
import typeinfo.pets.*;
class Apply {
public static >
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 extends ArrayList {
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);
}
}
}
public class Ja15_40{
public static void main(String[] args) throws Exception {
List shapes = new ArrayList();
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 squares = new ArrayList();
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.class, 10),
Shape.class.getMethod("rotate"));
Apply.apply(new FilledList(Square.class, 10),
Shape.class.getMethod("rotate"));
List lp=new ArrayList();
lp.add(new Dog());
lp.add(new Cat());
lp.add(new Pug());
Apply.apply(lp,Pet.class.getMethod("speak"));
}
} /* (Execute to see output) *///:~
练习41:
// Modify Fill2.java to use the classes in typeinfo.pets instead
// of the Pet classes.
// Using adapters to simulate latent typing.
// {main: Fill41Test}
import generics.coffee.*;
import java.util.*;
import net.mindview.util.*;
import static net.mindview.util.Print.*;
import typeinfo.pets.*;
interface Addable { void add(T t); }
class SimpleQueue implements Iterable {
private LinkedList storage = new LinkedList();
public void add(T t) { storage.offer(t); }
public T get() { return storage.poll(); }
public Iterator iterator() {
return storage.iterator();
}
}
class Fill2 {
// Classtoken version:
public static void fill(Addable 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 void fill(Addable addable,
Generator 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 implements Addable {
private Collection c;
public AddableCollectionAdapter(Collection c) {
this.c = c;
}
public void add(T item) { c.add(item); }
}
// A Helper to capture the type automatically:
class Adapter {
public static
Addable collectionAdapter(Collection c) {
return new AddableCollectionAdapter(c);
}
}
// To adapt a specific type, you can use inheritance.
// Make a SimpleQueue Addable using inheritance:
class AddableSimpleQueue
extends SimpleQueue implements Addable {
public void add(T item) { super.add(item); }
}
public class Ja15_41{
public static void main(String[] args) {
// Adapt a Collection:
List carrier = new ArrayList();
Fill2.fill(
new AddableCollectionAdapter(carrier),
Pet.class, 3);
// Helper method captures the type:
Fill2.fill(Adapter.collectionAdapter(carrier),
Dog.class, 2);
for(Pet c: carrier)
print(c);
print("----------------------");
// Use an adapted class:
AddableSimpleQueue coffeeQueue =
new AddableSimpleQueue();
Fill2.fill(coffeeQueue, Pug.class, 4);
Fill2.fill(coffeeQueue,Dog.class, 1);
for(Pet c: coffeeQueue)
print(c);
}
}
练习42:
/*
* Create two separate classes, with nothing in common. Each class should
* hold a value, and at least have methods that produce that value and
* perform a modification upon that value. Modify Functional.java so that
* it performs functional operations on collections of your classes (these
* operations do not have to be arithmetic as they are in Functional.java).
*/
import typeinfo.pets.*;
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 combine(T x, T y); }
interface UnaryFunction { R function(T x); }
interface Collector extends UnaryFunction {
T result(); // Extract result of collecting parameter
}
interface UnaryPredicate { boolean test(T x); }
class A implements UnaryPredicate{
public boolean test(Pet p){return p.getClass().getSimpleName().equals("Pet");};
}
class B implements UnaryPredicate{
public boolean test(Dog p){return p.getClass().getSimpleName().equals("Dog");};
}
public class Ja15_42 {
// Calls the Combiner object on each element to combine
// it with a running result, which is finally returned:
public static T
reduce(Iterable seq, Combiner combiner) {
Iterator 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 Collector
forEach(Iterable seq, Collector 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 List
transform(Iterable seq, UnaryFunction func) {
List result = new ArrayList();
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 List
filter(Iterable seq, UnaryPredicate pred) {
List result = new ArrayList();
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 {
public Integer combine(Integer x, Integer y) {
return x + y;
}
}
static class
IntegerSubtracter implements Combiner {
public Integer combine(Integer x, Integer y) {
return x - y;
}
}
static class
BigDecimalAdder implements Combiner {
public BigDecimal combine(BigDecimal x, BigDecimal y) {
return x.add(y);
}
}
static class
BigIntegerAdder implements Combiner {
public BigInteger combine(BigInteger x, BigInteger y) {
return x.add(y);
}
}
static class
AtomicLongAdder implements Combiner {
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 {
public BigDecimal function(BigDecimal x) {
return x.ulp();
}
}
static class GreaterThan>
implements UnaryPredicate {
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 {
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 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(4)));
print(forEach(li,
new MultiplyingIntegerCollector()).result());
print(forEach(filter(li, new GreaterThan(4)),
new MultiplyingIntegerCollector()).result());
MathContext mc = new MathContext(7);
List 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(new BigDecimal(3))));
// Use the prime-generation facility of BigInteger:
List lbi = new ArrayList();
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 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()));
List lp=Arrays.asList(new Pet());
print(filter(lp,new A()));
List lg=Arrays.asList(new Dog());
print(filter(lg,new B()));
}
}