package tij.generic; public class Test { 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); } } } class LinkedStack<T> { private static class Node<U> { U item; Node<U> next; Node() { this.item = null; this.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>(); 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; } }
在類名後面掛個<T>的意思就是,聲明一下,我這個類裏面要用到名字叫作T的泛型啦!java
package tij.generic; import java.util.ArrayList; import java.util.Random; public class Test { public static void main(String[] args) { RandomList<String> rs = new RandomList<>(); 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() + " "); } } 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())); } }
package tij.generic; import java.util.Iterator; import java.util.Random; public class Test { 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); } } interface Generator<T> { T next(); } class Coffee { private static long counter = 0; private final long id = counter++; public String toString() { return getClass().getSimpleName() + " " + id; } } class Mocha extends Coffee {} class Cappuccino extends Coffee {} class Latte extends Coffee {} class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> { private Class<?>[] types = {Latte.class, Mocha.class, Latte.class}; private static Random rand = new Random(47); public CoffeeGenerator() { } private int size = 0; public CoffeeGenerator(int sz) { this.size = sz; } @Override public Iterator<Coffee> iterator() { return new CoffeeIterator(); } @Override public Coffee next() { try { return (Coffee) types[rand.nextInt(types.length)].newInstance(); } 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(); } } }
對於static方法,沒法訪問泛型類的類型參數,因此若是static方法要使用泛型,這個方法就必須是泛型的。
檢討發放須要將泛型參數列表之餘返回值以前數組
package tij.generic; public class Test { public <T> void f(T x){ System.out.println(x.getClass().getName()); } public static void main(String[] args) { Test t=new Test(); t.f("x"); t.f(1); } }
package tij.generic; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { List<String> ls = New.list(); } } class New { public static <T> List<T> list() { return new ArrayList<T>(); } }
如今能夠了,別BB。
如今能夠顯式的類型說明安全
package tij.generic; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class Test { public static void main(String[] args) { List<String> ls = New.list(); f(New.<String>list()); m(New.map()); } static void f(List<String> x){ } static void m(Map<String ,List<? extends New>> m){ } } class New { public static <T> List<T> list() { return new ArrayList<T>(); } public static <K,V> Map<K,V> map(){ return new HashMap<K,V>(); } }
這段代碼沒毛病的,JDK1.8app
沒啥好說dom
package tij.generic; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { List<String> ls = makeList("A"); System.out.println(ls); ls = makeList("A", "B"); System.out.println(ls); } public static <T> List<T> makeList(T... args) { List<T> result = new ArrayList<T>(); for (T item : args) result.add(item); return result; } }
package tij.generic; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Random; public class Test { public static void main(String[] args) { Collection<Coffee> coffee = Generators.fill(new ArrayList<Coffee>(), new CoffeeGenerator(), 4); for (Coffee c : coffee) { System.out.println(c); } } } 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; } } interface Generator<T> { T next(); } class Coffee { private static long counter = 0; private final long id = counter++; public String toString() { return getClass().getSimpleName() + " " + id; } } class Mocha extends Coffee {} class Cappuccino extends Coffee {} class Latte extends Coffee {} class CoffeeGenerator implements Generator<Coffee>, Iterable<Coffee> { private Class<?>[] types = {Latte.class, Mocha.class, Latte.class}; private static Random rand = new Random(47); public CoffeeGenerator() { } private int size = 0; public CoffeeGenerator(int sz) { this.size = sz; } @Override public Iterator<Coffee> iterator() { return new CoffeeIterator(); } @Override public Coffee next() { try { return (Coffee) types[rand.nextInt(types.length)].newInstance(); } 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(); } } }
fill方法能夠透明的應用於實現了泛型接口的類。eclipse
package tij.generic; public class Test { 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()); } } } class CountedObject { private static long counter = 0; private final long id = counter++; public long id() { return id; } public String toString() { return "CountedObject " + id; } } class BasicGenerator<T> implements Generator<T> { private Class<T> type; public BasicGenerator(Class<T> type) { this.type = type; } public T next() { try { return type.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } } public static <T> Generator<T> create(Class<T> type) { return new BasicGenerator<T>(type); } } interface Generator<T> { T next(); }
我認爲沒什麼意義ide
沒什麼卵用工具
package tij.generic; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Random; public class Test { 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); } } } interface Generator<T> { T next(); } 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; } } class Customer { private static long counter = 1; private final long id = counter++; private Customer() { } public String toString() { return "Customer" + id; } 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; } public static Generator<Teller> generator = new Generator<Teller>() { public Teller next() { return new Teller(); } }; }
什麼gui東西ui
本身看書吧this
package tij.generic; import java.lang.reflect.Array; import java.util.Arrays; public class Test { 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)); } } class ArrayMaker<T> { private Class<T> kind; ArrayMaker(Class<T> kind) { this.kind = kind; } T[] create(int size) { return (T[]) Array.newInstance(kind, size); } }
package tij.generic; public class Test { static final int SIZE = 100; static Generic<Integer>[] gia; public static void main(String[] args) { gia = (Generic<Integer>[]) new Object[SIZE]; gia = (Generic<Integer>[]) new Generic[SIZE]; System.out.println(gia.getClass()); gia[0] = new Generic<Integer>(); // gia[1]=new Object(); } } class Generic<T> {} class ArrayOfGeneric { }
package tij.generic; import java.awt.Color; public class Test { public static void main(String[] args) { Solid<Bounded> solid = new Solid<>(new Bounded()); solid.color(); solid.getY(); solid.weight(); } } interface HasColor { Color getColor(); } class Colored<T extends HasColor> { T item; Colored(T item) { this.item = item; } T getItem() { return item; } Color color() { return item.getColor(); } } class Dimension { public int x, y, z; } class ColoredDimension<T extends Dimension & HasColor> { T item; ColoredDimension(T item) { this.item = item; } T getItem() { return item; } Color color() { return item.getColor(); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } } interface Weight { int weight(); } class Solid<T extends Dimension & HasColor & Weight> { T item; Solid(T item) { this.item = item; } T getItem() { return item; } 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 Color getColor() { return null; } public int weight() { return 0; } }
經過上述代碼我能夠知道,經過對檢討進行集成的限定,能夠限制泛型的類型
接下來能夠看到如何在繼承的每一個層次上添加邊界限制:
package tij.generic; import java.awt.Color; public class Test { public static void main(String[] args) { Solid2<Bounded> solid = new Solid2<>(new Bounded()); solid.color(); solid.getY(); solid.weight(); } } interface HasColor { Color getColor(); } 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); } Color color() { return item.getColor(); } } class Dimension { public int x, y, z; } class ColoredDimension2<T extends Dimension & HasColor> extends Colored2<T> { ColoredDimension2(T item) { super(item); } T getItem() { return item; } Color color() { return item.getColor(); } int getX() { return item.x; } int getY() { return item.y; } int getZ() { return item.z; } } interface Weight { int weight(); } class Solid2<T extends Dimension & HasColor & Weight> extends ColoredDimension2<T> { Solid2(T item) { super(item); } int weight() { return item.weight(); } } class Bounded extends Dimension implements HasColor, Weight { public Color getColor() { return null; } public int weight() { return 0; } }
經過上面兩段代碼能夠知道,在繼承的過程當中,在每一個層次上的類型參數都被添加了必定的邊界進行限制。
通配符就是泛型裏面的問號,結合eclipse的提示看一下參數類型會對理解這節有很大幫助
package tij.generic; public class Test { public static void main(String[] args) { Fruit[] fruit=new Apple[10]; fruit[0]=new Apple(); fruit[1]=new Jonathan(); try{ fruit[0]=new Fruit(); }catch(Exception e){ System.out.println(e); } try{ fruit[0]=new Orange(); }catch(Exception e){ System.out.println(e); } } } class Fruit{} class Apple extends Fruit{} class Jonathan extends Fruit{} class Orange extends Fruit{}
經過以上代碼能夠知道,明明是一個apple數組,在接收jonathan對象的時候,編譯器並無報錯,而在運行的時候纔會報錯,經過泛型,能夠將這個錯誤轉化爲編譯期的錯誤
List<Fruit> flist = new ArrayList<Apple>();
這段代碼會報錯
List<? extends Fruit> flist = new ArrayList<Apple>();
這段代碼不只不會報錯,並且沒辦法往裏傳遞任何信息。可是這個flist卻能夠指向各類是fruit的ArrayLIst對象。
由於編譯器並不知道你到底想要啥
如圖,參數類型是null
代碼1:
package tij.generic; import java.util.Arrays; import java.util.List; public class Test { public static void main(String[] args) { List<? extends Fruit> flist = Arrays.asList(new Apple()); Apple a = (Apple) flist.get(0); flist.contains(new Apple()); flist.indexOf(new Apple()); } } class Fruit {} class Apple extends Fruit {} class Jonathan extends Fruit {} class Orange extends Fruit {}
代碼2:
package tij.generic; import java.util.Arrays; import java.util.List; public class Test { public static void main(String[] args) { Holder<Apple> Apple = new Holder<Apple>(new Apple()); Apple d = Apple.get(); Apple.set(d); Holder<? extends Fruit> fruit = Apple; Fruit p = fruit.get(); d = (Apple) fruit.get(); // fruit.set(new Apple()); fruit.setOb(new Apple()); System.out.println(fruit.equals(d)); } } class Fruit {} class Apple extends Fruit {} class Jonathan extends Fruit {} class Orange extends Fruit {} class Holder<T> { private T value; public Holder() {} public Holder(T val) { value = val; } public void set(T val) { value = val; } public void setOb(Object obj) { this.value = (T) obj; } public T get() { return value; } public boolean equals(Object obj) { return value.equals(obj); } }
代碼1:
package tij.generic; import java.util.List; public class Test { public static void main(String[] args) {} } class Fruit {} class Apple extends Fruit {} class Jonathan extends Apple {} class Orange extends Fruit {} class SuperTypeWildcards { static void writerTo(List<? super Apple> apples) { apples.add(new Apple()); apples.add(new Jonathan()); // apples.add(new Fruit()); } }
? super Apple的意思就是,只要是Apple或者Apple的爹的意思,但事實上,正如上面所說,編譯器並不知道你這個通配符表明的是什麼,
可是在super這裏,至少全部的apple和apple的子類,全都是apple,這沒錯的。
代碼3:
package tij.generic; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) { GenericWriting.f1(); GenericWriting.f2(); } } class Fruit {} class Apple extends Fruit {} class Jonathan extends Apple {} class Orange extends Fruit {} 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()); fruit.add(new 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()); } }
實際上是能夠的,書上說不能夠
代碼3:
package tij.generic; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Test { public static void main(String[] args) { GenericWriting.f1(); GenericWriting.f2(); GenericWriting.f3(); } } class Fruit {} class Apple extends Fruit {} class Jonathan extends Apple {} class Orange extends Fruit {} class GenericWriting { static List<Apple> apples = Arrays.asList(new Apple()); static List<Fruit> fruit = Arrays.asList(new Fruit()); static <T> T readExact(List<T> list) { return list.get(0); } static void f1() { Apple a = readExact(apples); Fruit f = readExact(fruit); f = readExact(apples); } static class Reader<T> { T readExact(List<T> list) { return list.get(0); } } static void f2() { Reader<Fruit> fruitReader = new Reader<Fruit>(); Fruit f = fruitReader.readExact(apples);// error } static class CovariantReader<T> { T readCovariant(List<? extends T> list) { return list.get(0); } } static void f3() { CovariantReader<Fruit> fruitReader = new CovariantReader<Fruit>(); Fruit f = fruitReader.readCovariant(fruit); Fruit a = fruitReader.readCovariant(apples); CovariantReader<Apple> appleReader = new CovariantReader<Apple>(); Apple ap = appleReader.readCovariant(apples); } }
這是一次對比
class Wildcards{ static void rawArgs(Holder holder,Object arg){ holder.set(arg); holder.set(new Wildcards()); // T t=holder.get(); // Error Object obj=holder.get(); } static void unboundedArg(Holder<?> holder,Object arg){ // holder.set(arg); // holder.set(new Wildcards()); // Error 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); T t=holder.get(); return t; } static <T> void wildSupertype(Holder<? super T> holder,T arg){ holder.set(arg); // T t=holder.get(); Object obj=holder.get(); } }
破事兒真多,這玩意記不過來,邊用邊記吧,
書上看看得了
package tij.generic; public class Test { static <T> void f1(Holder<T> holder) { T t = holder.get(); System.out.println(t.getClass()); } static void f2(Holder<?> holder) { f1(holder); } public static void main(String[] args) { Holder raw = new Holder<Integer>(1); f2(raw); f1(raw); } } 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); } }
interface Payable<T>{} class Employee implements Payable<Employee>{} class Hourly extends Employee implements Payable<Hourly>{ }
package tij.generic; public class Test { 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 + " "); } } } 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; } public T pop() { return (T) storage[--index]; } }
class GenericType<T>{} class CuriouslyRecurringGeneric extends GenericType<CuriouslyRecurringGeneric>{ }
package tij.generic; public class Test { public static void main(String[] args) { BasicOther b = new BasicOther(); BasicOther b2 = new BasicOther(); b.set(new Other()); Other other = b.get(); b.f(); } } class BasicHolder<T> { T element; void set(T arg) { element = arg; } T get() { return element; } void f() { System.out.println(element.getClass()); } } class Other {} class BasicOther extends BasicHolder<Other> {}
package tij.generic; public class Test { public static void main(String[] args) { A a = new A(); a.set(new A()); a = a.set(new A()).get(); a = a.get(); B b = new B(); b.set(a); a = b.get(); C c = new C(); c = c.setAndGet(new C()); } } class BasicHolder<T> { T element; void set(T arg) { element = arg; } T get() { return element; } void f() { System.out.println(element.getClass()); } } class SelfBounded<T extends SelfBounded<T>> { T element; SelfBounded<T> set(T arg) { this.element = arg; return this; } T get() { return element; } } class A extends SelfBounded<A> {} class B extends SelfBounded<A> {} class C extends SelfBounded<C> { C setAndGet(C arg) { set(arg); return get(); } } class D {} class E extends SelfBounded<D> {} class F extends SelfBounded {}
class Base{} class Derived extends Base{} interface OrdinaryGetter{ Base get(); } interface DerivedGetter extends OrdinaryGetter{ Derived get(); }
重寫方法
interface GenericGetter<T extends GenericGetter<T>> { T get(); } interface Getter extends GenericGetter<Getter> {} class GenericsAndReturnTypes { void test(Getter g) { Getter result = g.get(); GenericGetter gg = g.get(); } }
自限定泛型
class OrdinarySetter{ void set(Base base){ System.out.println("OrdinarySetter.set(Base)"); } } class DerivedSetter extends OrdinarySetter{ void set(Derived derived){ System.out.println("DerivedSetter.set(Derived)"); } }
這是重載,不是重寫
interface SelfBoundSetter<T extends SelfBoundSetter<T>>{ void set(T arg); } interface Setter extends SelfBoundSetter<Setter>{} class SelfBoundingAndCovariantArguments{ void testA(Setter s1,Setter s2,SelfBoundSetter sbs){ s1.set(s2); s1.set(sbs); } }
package tij.generic; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Test { @SuppressWarnings("unchecked") static void oldStyleMethod(List probablyLatte) { probablyLatte.add(new Cappuccino()); } public static void main(String[] args) { List<Latte> latte = new ArrayList<Latte>(); oldStyleMethod(latte); List<Latte> latte2 = Collections.checkedList(new ArrayList<Latte>(), Latte.class); oldStyleMethod(latte2); } } class Coffee {} class Latte extends Coffee {} class Cappuccino extends Coffee {}
package tij.generic; import java.util.ArrayList; import java.util.List; public class Test { 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 { runner.processAll(); } catch (Failure1 e) { // TODO Auto-generated catch block System.out.println(e); } ProcessRunner<Integer, Failure2> runner2 = new ProcessRunner<Integer, Failure2>(); for (int i = 0; i < 3; i++) runner2.add(new Processor2()); try { runner2.processAll(); } catch (Failure2 e) { // TODO Auto-generated catch block System.out.println(e); } } } 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; @Override public void process(List<String> resultCollector) throws Failure1 { if (count-- > 1) resultCollector.add("Hep!"); else resultCollector.add("Ho!"); System.out.println(resultCollector); if (count < 0) { throw new Failure1(); } } } class Failure2 extends Exception {} class Processor2 implements Processor<Integer, Failure2> { static int count = 2; @Override public void process(List<Integer> resultCollector) throws Failure2 { if (count-- == 0) resultCollector.add(47); else resultCollector.add(11); System.out.println(resultCollector); if (count < 0) throw new Failure2(); } }
說實話,這有什麼卵意義麼
package tij.generic; import java.util.Date; public class Test { 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()); } } interface TimeStamped { long getStamp(); } class TimeStampedImp implements TimeStamped { private final long timeStamp; public TimeStampedImp() { super(); this.timeStamp = new Date().getTime(); } public long getStamp() { return this.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 { void set(String val); 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 { private TimeStamped timeStamp = new TimeStampedImp(); private SerialNumbered serialNumber = new SerialNumberedImp(); @Override public long getSerialNumber() { return serialNumber.getSerialNumber(); } @Override public long getStamp() { return timeStamp.getStamp(); } }
package tij.generic; import java.util.Date; public class Test { public static void main(String[] args) { TimeStamped t = new TimeStamped(new Basic()); TimeStamped t2 = new TimeStamped(new SerialNumbered(new Basic())); SerialNumbered s = new SerialNumbered(new Basic()); SerialNumbered s2 = new SerialNumbered(new TimeStamped(new Basic())); } } class Basic { private String value; void set(String val) { this.value = val; }; 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); this.timeStamp = new Date().getTime(); } public long getStamp() { return this.timeStamp; } } class SerialNumbered extends Decorator { public SerialNumbered(Basic basic) { super(basic); } private static long counter = 1; private final long serialNumber = counter++; public long getSerialNumber() { return serialNumber; } }
以後pass不看了,費勁
end