java程式設計思想讀書筆記 第十五章 泛型 (匿名內部類和擦除)
阿新 • • 發佈:2018-12-26
1.匿名內部類
泛型還可以應用於內部類以及匿名內部類。下面的例子使用匿名內部類實現了Generator介面:
public 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>() {
@Override
public Customer next() {
return new Customer();
}
};
}
}
public class Teller {
private static long counter = 1;
private final long id = counter++;
private Teller (){}
@Override
public String toString() {
return "Teller" + id;
}
public static Generator<Teller> generator = new Generator<Teller>() {
@Override
public Teller next() {
return new Teller();
}
};
}
public class BankTeller {
public static void serve(Teller t,Customer c){
System.out.println(t + "serve" + c);
}
public static void main(String[] args) {
Random random = 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(random.nextInt(tellers.size())), c);
}
}
}
output:
Teller3serveCustomer1
Teller2serveCustomer2
Teller3serveCustomer3
Teller1serveCustomer4
Teller1serveCustomer5
Teller3serveCustomer6
Teller1serveCustomer7
Teller2serveCustomer8
Teller3serveCustomer9
Teller3serveCustomer10
Teller2serveCustomer11
Teller4serveCustomer12
Teller2serveCustomer13
Teller1serveCustomer14
Teller1serveCustomer15
Customer和Teller類都只有private的構造器,這可以強制你必須使用Generator物件(這裡的Generator介面和Generators類都是前兩篇部落格出現的)。Customer有一個generator()方法,每次執行它都會生成一個新的Generator物件。由於Customer中的generator()方法,以及Teller中的Generator物件都宣告成了static的,所以它們無法作為介面的一部分,因此無法用介面這種特定的慣用法來泛化這二者。儘管如此,它們在fill()方法中都工作得很好。
2.擦除的神祕之處
在泛型的程式碼內部,無法獲得任何有關泛型引數型別的資訊。因此,你可以知道諸如型別引數識別符號和泛型型別邊界這類的資訊——你卻無法知道用來建立某個特定例項的實際的型別引數。java泛型時使用擦除來實現的,這意味著當你再使用泛型時,任何具體的型別資訊都被擦除了,你唯一知道的就是你在使用一個物件。因此List 和List在執行時事實上是相同的型別。這兩種形式都被擦除成它們的“原生”型別,即List。
擦除主要的正當理由是從非泛化程式碼到泛化程式碼的轉變過程,以及在不破壞現有類庫的情況下,將泛型融入java語音。擦除使得現有的非泛型客戶端程式碼能夠在不改變的情況下繼續使用,直至客戶端準備好用泛型重寫這些程式碼。擦除的代價是顯著的。泛型不能用於顯式地引用執行時型別的操作之中,例如轉型、instanceof和操作和new表示式。