泛型的引入

来源:互联网 发布:嵌入式与人工智能关系 编辑:程序博客网 时间:2024/06/15 23:50

一 Java集合设计的两个问题

1 集合对元素类型没有任何限制,这样可能引发一些问题:例如想创建一个只能保存Dog对象的集合,但程序也可以轻易地将Cat对象“丢”进去,所以可能引发异常。

2 由于把对象“丢进”集合时,集合丢失了对象的状态信息,集合只知道它盛装的是Object,因此取出集合元素后通常还需要进行强制类型转换。这种强制类型转换既会增加编程的复杂度、也可能引发ClassCastException。

 

二 编译时不检查异常类型

1 代码示例

import java.util.*;public class ListErr{public static void main(String[] args){// 创建一个只想保存字符串的List集合List strList = new ArrayList();strList.add("Java");strList.add("Android");// "不小心"把一个Integer对象"丢进"了集合strList.add(5);     // ①strList.forEach(str -> System.out.println(((String)str).length())); // ②}}

2 运行结果

4

7

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
        at ListErr.lambda$main$0(ListErr.java:14)
        at java.util.ArrayList.forEach(Unknown Source)
        at ListErr.main(ListErr.java:14)

3 代码分析

程序创建了一个List集合,而且只希望该List集合保存字符串对象,但程序不能进行任何限制,如果在①处不小心把一个Interger对象“丢进了集合”,这将导致程序在②处引发ClassCastException异常,因为程序试图把一个Interger对象转换为String类型。

 

三泛型的引入

1 泛型介绍

从Java 5以后,Java引入了“参数化类型”的概念,允许程序在创建集合时指定集合元素的类型。列如:List<String>,这表明该List只能保存字符串类型的对象。Java的参数化类型被称为泛型(Generic)。

2 代码示例

import java.util.ArrayList;import java.util.List;public class GenericList{public static void main(String[] args){// 创建一个只想保存字符串的List集合List<String> strList = new ArrayList<String>();  // ①strList.add("Java");strList.add("Android");// 下面代码将引起编译错误strList.add(5);    // ②strList.forEach(str -> System.out.println(str.length())); // ③}}

3 运行结果

E:\test\Java\Java8\fanxing\src>javac GenericList.java
GenericList.java:14: 错误: 对于add(int), 找不到合适的方法
                strList.add(5);    // ②
                       ^
    方法 Collection.add(String)不适用
      (参数不匹配; int无法转换为String)
    方法 List.add(String)不适用
      (参数不匹配; int无法转换为String)
注: 某些消息已经过简化; 请使用 -Xdiags:verbose 重新编译以获得完整输出
1 个错误

4 代码分析

在集合中使用泛型后带来如下优势:

  • 程序再也不能“不小心”把其他对象“丢进”strList集合中,在编译的时候就能够发现问题了。
  • 程序更加简洁,集合自动记住所有集合元素的数据类型,从而无需对集合元素进行强制类型转换。

四 Java 7 泛型的菱形语法

1 菱形介绍

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

List<String> strList = new ArrayList<String>();

上面这条语句中粗体代码部分完全多余,但再Java 7以前这是必须的,不能省略。从Java 7开始,Java允许在构造器后不带需要带完整的泛型信息,只要一对(<>)即可,Java可以推断尖括号应该是什么泛型信息。即上面的语句可以改写成如下形式:

List<String> strList = new ArrayList<>();

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

2 代码示例

import java.util.*;public class DiamondTest{public static void main(String[] args){// Java自动推断出ArrayList的<>里应该是StringList<String> books = new ArrayList<>();books.add("Java");books.add("Android");// 遍历books集合,集合元素就是String类型books.forEach(ele -> System.out.println(ele.length()));// Java自动推断出HashMap的<>里应该是String , List<String>Map<String , List<String>> schoolsInfo = new HashMap<>();// Java自动推断出ArrayList的<>里应该是StringList<String> schools = new ArrayList<>();schools.add("床前明月光");schools.add("疑是地上霜");schools.add("举头望明月");schools.add("低头思故乡");schoolsInfo.put("李白" , schools);// 遍历Map时,Map的key是String类型,value是List<String>类型schoolsInfo.forEach((key , value) -> System.out.println(key + "-->" + value));}}

3 运行结果

E:\test\Java\Java8\fanxing\src>java DiamondTest
4
7
李白-->[床前明月光, 疑是地上霜, 举头望明月, 低头思故乡]

4 代码分析

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

0 0
原创粉丝点击