Richard Warburton與Raoul-Gabriel Urma在Devoxx UK 2015上回顧Java泛型歷史
Richard與Raoul向廣大開發者提供關于Java 8的 培訓課程 。近日,二人在Devoxx UK 2015上共同進行了一場 演講 ,回顧了Java泛型的起源與動機、介紹了目前一些不為人知的特性,同時對Java 10進行了展望。該演講由3個精彩的部分構成:泛型的過去、現在與未來。
過去
正如Richard與Raoul所說,在引入泛型之前,Java中的集合是很難使用的,因為其中包含的是Object,我們無法確定集合中元素 的具體類型。如果將任意類型的對象添加到集合中,那么其類型信息就會丟失,在獲取對象時,開發者不得不手工將其強制轉換為相關類型才能使用它。
這不僅會導致代碼變得異常笨重,還使得我們無法限制添加到集合中的對象類型。2004年發布的 Java 5 通過增加泛型特性解決了這個問題,不過為了保持向后兼容,泛型只能通過 類型擦除 來實現。
現在
接下來,Richard與Raoul談到了目前Java泛型的一些特性,特別是一些不為人知的特性:交叉類型、通配符與F綁定多態。
“交叉類型”特性使用起來相對簡單,它指的是集合中元素的類型需要繼承兩個或多個類或接口。而通配符則不那么好理解。Richard指出:
通配符是個難以理解且難以使用的特性。過去在Java中,你無法表達出參數的協變與逆變的概念,對于聲明為某個接口類型的變量來說,你每次都需要在變量聲明時表示出其類型信息。這將復雜性由庫的作者推給了每一個人。
盡管如此,Richard與Raoul通過將不同的通配符關聯到生產者與消費者的概念上闡述了程序員如何可以從中獲益。
生產者會生產出對象供其他類使用。為了讓這些類知道該如何使用這些對象,我們使用了一個“契約”,表示出可以提供的最為具體的類型。該“契約” 采取了繼承通配符的形式,具體來說就是Class<? extends T>。這表示泛型類所使用的類型是T或T的子類,這意味著你可以使用T所具有的所有行為。
與之類似,消費者接收并使用對象。為了讓其他類知道可以將何種類型的對象傳遞給消費者,消費者需要指定保證會接收的最具體的類型。它采取了 super通配符的形式,具體來說就是Class<? super T>。該符號表示我們打算將類型為T的對象賦給消費者,這樣消費者就可以處理類型T或T的父類的對象了。
最后,二位演講者又談到了F綁定多態,他們將其稱作“奇特的遞歸泛型模式”(類比于C++中 奇特的遞歸模板模式 )。在這種泛型形式中,類型參數會遞歸地引用泛型類型本身,如下所示:
public interface ClassName<T extends ClassName<T>>
正如演講中所提到的,該特性在泛型類型中的方法需要返回模板類型時是非常有用的,比如說克隆對象時。
未來
在演講的最后一部分中,二位演講者繼續介紹目前尚在討論之中的對泛型的一些改進,這些改進可能會添加到Java 10中。一方面,目前正在解決原生類型的泛型問題,這樣就無需自動裝箱與自動拆箱了;這與 項目Valhalla 緊密相關。Richard說到,這些修改可以讓程序員編寫出下面這樣的代碼:
List<int> integers = new ArrayList<>(); integers.add(1);
Richard說到,底層可以將其實現為int[]而非目前的Integer[],這么做一方面可以減少內存占用,另一方面可以讓CPU的緩存預先抓取器工作得更好。他補充說到:“這會改進性能,就像C#的具化泛型一樣”。
另一方面,讓庫的作者在接口聲明而非現在這樣在接口使用時表明變化,可以簡化協變與逆變的處理。這種聲明變量的形式可以讓大多數開發者從通配符泛型中獲益,從而無需了解關于底層的更多信息,同時高級程序員還可以覆寫這種默認行為以實現更加專門的代碼。
查看英文原文: Richard Warburton and Raoul-Gabriel Urma Review the History of Generics in Java at Devoxx UK