在 Java 7 版本以前,如果使用帶泛型的介面、類定義變數,那麼呼叫構造器建立物件時構造器的後面也必須帶泛型,這顯得有些多餘了。例如如下兩條語句:
List<String> strList = new ArrayList<String>();
Map<String, Integer> scores = new HashMap<String, Integer>();
上面兩條語句中等號右邊的尖括號部分完全是多餘的,Java 7 版本以前是必需的,不能省略。從 Java 7 開始,Java 允許在構造器後不帶完整的泛型資訊,只要給出一對尖括號
<>
即可。Java 可以推斷出尖括號裡應該是什麼泛型資訊。
即上面兩條語句可以改寫為如下形式:
List<String> strList = new ArrayList<>();
Map<String, Integer> scores = new HashMap<>();
把兩個尖括號並排放在一起非常像一個菱形,這種語法也就被稱為
“菱形”語法。下面程式示範了 Java 7 的菱形語法。
public class Test {
public static void main(String[] args) {
// Java自動推斷出ArrayList的<>裡應該是String
List<String> names = new ArrayList<>();
names.add("C語言中文網Java入門教學");
names.add("C語言中文網Spring入門教學");
// 遍歷names集合,集合元素就是String型別
names.forEach(ele -> System.out.println(ele.length()));
// Java 自動推斷出 HashMap 的<>裡應該是 String,List<String>
Map<String, List<String>> coursesInfo = new HashMap<>();
// Java自動推斷出ArrayList的<>裡應該是String
List<String> courses = new ArrayList<>();
courses.add("Java入門教學");
courses.add("Python基礎教學");
coursesInfo.put("C語言中文網", courses);
// 遍歷 Map 時,Map 的 key 是 String 型別,value List<String>型別
coursesInfo.forEach((key, value) -> System.out.println(key + "-->" + value));
}
}
上面程式中程式碼第 4、10 和 12 行程式碼就是“菱形”語法的範例。從該程式不難看出,“菱形”語法對原有的泛型並沒有改變,只是更好地簡化了泛型程式設計。
Java 9 再次增強了“菱形”語法,它甚至允許在建立匿名內部類時使用菱形語法,Java 可根據上下文來推斷匿名內部類中泛型的型別。下面程式示範了在匿名內部類中使用菱形語法。
interface Foo<T> {
void test(T t);
}
public class AnnoymousTest {
public static void main(String[] args) {
// 指定Foo類中泛型為String
Foo<String> f = new Foo<>() {
// test()方法的引數型別為String
public void test(String t) {
System.out.println("test 方法的 t 引數為:" + t);
}
};
// 使用泛型萬用字元,此時相當於萬用字元的上限為Object
Foo<?> fo = new Foo<>() {
// test()方法的引數型別為Object
public void test(Object t) {
System.out.println("test 方法的 Object 引數為:" + t);
}
};
// 使用泛型萬用字元,萬用字元的上限為Number
Foo<? extends Number> fn = new Foo<>() {
// 此時test ()方法的引數型別為Number
public void test(Number t) {
System.out.println("test 方法的 Number 引數為:" + t);
}
};
}
}
上面程式先定義了一個帶泛型宣告的介面,接下來第 8、15 和 22 行程式碼分別示範了在匿名內部類中使用菱形語法。第 8 行程式碼宣告變數時明確地將泛型指定為 String 型別,因此在該匿名內部類中 T 型別就代表了 String 型別;第 15 行程式碼宣告變數時使用萬用字元來代表泛型(相當於萬用字元的上限為 Object),因此系統只能推斷出 T 代表 Object,所以在該匿名內部類中 T 型別就代表了 Object 型別;第 22 行程式碼宣告變數時使用了帶上限(上限是 Number)的萬用字元,因此系統可以推斷出 T 代表 Number 類。
無論以上哪種方式,Java 9 都允許在使用匿名內部類時使用菱形語法。