欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Java 9 的新功能:不可变集合

最编程 2024-05-01 09:16:05
...

在 Java 7 版本以前,如果使用带泛型的接口、类定义变量,那么调用构造器创建对象时构造器的后面也必须带泛型,这显得有些多余了。例如如下两条语句:

 
 
  1. List<String> strList = new ArrayList<String>();
  2. Map<String, Integer> scores = new HashMap<String, Integer>();

从 Java 7 开始,Java 允许在构造器后不带完整的泛型信息,只要给出一对尖括号<>即可。Java 可以推断出尖括号里应该是什么泛型信息。

即上面两条语句可以改写为如下形式:

 
 
  1. List<String> strList = new ArrayList<>();
  2. Map<String, Integer> scores = new HashMap<>();

把两个尖括号并排放在一起非常像一个菱形,这种语法也就被称为“菱形”语法。下面程序示范了 Java 7 的菱形语法。

 
 
  1. public class Test {
  2. public static void main(String[] args) {
  3. // Java自动推断出ArrayList的<>里应该是String
  4. List<String> names = new ArrayList<>();
  5. names.add("JAVA中文网Java入门教程");
  6. names.add("JAVA中文网Spring入门教程");
  7. // 遍历names集合,集合元素就是String类型
  8. names.forEach(ele -> System.out.println(ele.length()));
  9. // Java 自动推断出 HashMap 的<>里应该是 String,List<String>
  10. Map<String, List<String>> coursesInfo = new HashMap<>();
  11. // Java自动推断出ArrayList的<>里应该是String
  12. List<String> courses = new ArrayList<>();
  13. courses.add("Java入门教程");
  14. courses.add("Python基础教程");
  15. coursesInfo.put("JAVA", courses);
  16. // 遍历 Map 时,Map 的 key 是 String 类型,value List<String>类型
  17. coursesInfo.forEach((key, value) -> System.out.println(key + "-->" + value));
  18. }
  19. }

上面程序中代码第 4、10 和 12 行代码就是“菱形”语法的示例。从该程序不难看出,“菱形”语法对原有的泛型并没有改变,只是更好地简化了泛型编程。

Java 9 再次增强了“菱形”语法,它甚至允许在创建匿名内部类时使用菱形语法,Java 可根据上下文来推断匿名内部类中泛型的类型。下面程序示范了在匿名内部类中使用菱形语法。

首先定义一个接口:

 
 
  1. interface Foo<T> {
  2. void test(T t);
  3. }

创建实现类:

 
 
  1. public class AnnoymousTest {
  2. public static void main(String[] args) {
  3. // 指定Foo类中泛型为String
  4. Foo<String> f = new Foo<>() {
  5. // test()方法的参数类型为String
  6. public void test(String t) {
  7. System.out.println("test 方法的 t 参数为:" + t);
  8. }
  9. };
  10. // 使用泛型通配符,此时相当于通配符的上限为Object
  11. Foo<?> fo = new Foo<>() {
  12. // test()方法的参数类型为Object
  13. public void test(Object t) {
  14. System.out.println("test 方法的 Object 参数为:" + t);
  15. }
  16. };
  17. // 使用泛型通配符,通配符的上限为Number
  18. Foo<? extends Number> fn = new Foo<>() {
  19. // 此时test ()方法的参数类型为Number
  20. public void test(Number t) {
  21. System.out.println("test 方法的 Number 参数为:" + t);
  22. }
  23. };
  24. }
  25. }

上面程序先定义了一个带泛型声明的接口,接下来第 4、11 和 18 行代码分别示范了在匿名内部类中使用菱形语法。第 4行代码声明变量时明确地将泛型指定为 String 类型,因此在该匿名内部类中 T 类型就代表了 String 类型;第 11 行代码声明变量时使用通配符来代表泛型(相当于通配符的上限为 Object),因此系统只能推断出 T 代表 Object,所以在该匿名内部类中 T 类型就代表了 Object 类型;第 18 行代码声明变量时使用了带上限(上限是 Number)的通配符,因此系统可以推断出 T 代表 Number 类。

无论以上哪种方式,Java 9 都允许在使用匿名内部类时使用菱形语法。

推荐阅读