一 Java集合设计的两个问题
1 集合对元素类型没有任何限制,这样可能引发一些问题:例如想创建一个只能保存Dog对象的集合,但程序也可以轻易地将Cat对象“丢”进去,所以可能引发异常。
2 由于把对象“丢进”集合时,集合丢失了对象的状态信息,集合只知道它盛装的是Object,因此取出集合元素后通常还需要进行强制类型转换。这种强制类型转换既会增加编程的复杂度、也可能引发ClassCastException。
二 编译时不检查异常类型
1 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import 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 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import 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:testJavaJava8fanxingsrc>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 代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25import java.util.*; public class DiamondTest { public static void main(String[] args) { // Java自动推断出ArrayList的<>里应该是String List<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的<>里应该是String List<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:testJavaJava8fanxingsrc>java DiamondTest
4
7
李白-->[床前明月光, 疑是地上霜, 举头望明月, 低头思故乡]
4 代码分析
上面的程序有3行就是“菱形”语法的示例。从该程序不难看出,“菱形”语法对原有的泛型并没有改变,只是更好地简化了泛型编程。
最后
以上就是可靠花瓣最近收集整理的关于泛型的引入的全部内容,更多相关泛型内容请搜索靠谱客的其他文章。
发表评论 取消回复