泛型的引入

一 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的<>里应该是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:\test\Java\Java8\fanxing\src>java DiamondTest
4
7
李白-->[床前明月光, 疑是地上霜, 举头望明月, 低头思故乡]

4 代码分析

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 是 Java 5 引入的一个新特性,它可以让程序员在编写代码时更加灵活地处理数据类可以让代码更加简洁,可读性更强,同时还可以提高代码的安全性。 使用的主要目的是为了避免类转换的问题。在 Java 5 之前,对于容器类(如 List、Set、Map 等),它们可以存储任意类的对象,但是获取容器中的元素时需要进行类转换,这往往会导致运行时异常。而使用之后,可以在编译时就确定容器中元素的类,从而避免类转换的问题。 Java 中的主要包括以下几个部分: 1. 类参数:使用尖括号(<>)来定义,可以理解为占位符,表示一种未知类。 2. 类:使用类参数来定义类,在类中可以使用类参数来定义属性、方法返回值、方法参数等。 3. 接口:与类类似,可以使用类参数来定义接口中的方法。 4. 方法:在普通方法中使用类参数来定义方法返回值、方法参数等。 下面是一个简单的类的例子: ``` public class Box<T> { private T data; public Box(T data) { this.data = data; } public T getData() { return data; } public void setData(T data) { this.data = data; } } ``` 在这个例子中,Box 类使用了一个类参数 T,表示 Box 中存储的数据类是未知的。在构造方法和属性的 getter/setter 方法中都使用了 T,表示返回值或参数的类都是 T 类。这样,使用 Box 类时就可以指定具体的类,例如: ``` Box<String> stringBox = new Box<String>("Hello"); String data = stringBox.getData(); ``` 在这个例子中,创建了一个 Box 类为 String 的对象,并调用了它的 getData 方法获取数据,不需要进行类转换,因为在编译时就已经确定了数据类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值