一 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行就是“菱形”语法的示例。从该程序不难看出,“菱形”语法对原有的泛型并没有改变,只是更好地简化了泛型编程。
相关推荐
泛型引入的主要目的是提高代码的可读性和可维护性,同时减少类型转换的冗余。下面将详细讨论Java中泛型的使用及相关知识点。 1. 泛型的基本概念 泛型是Java SE 5.0引入的新特性,它允许在类、接口和方法中使用类型...
泛型引入的主要目的是在编译时期检查类型安全,并且在运行时提供更好的性能。在类定义中使用尖括号()来声明类型参数,例如: ```java public class Container<T> { private T item; public void set(T item) ...
泛型引入的主要目的是在编译时捕获类型错误,而不是在运行时。通过使用泛型,我们可以避免强制类型转换,并确保在处理集合或自定义数据结构时,只允许正确的类型进行操作。在Java中,我们使用尖括号 `<T>` 来声明...
泛型引入的主要目的是提供类型安全,确保在集合中存储的对象类型是预期的。泛型通过类型参数化来实现,允许在声明类、接口或方法时指定一种或多种类型参数。 1. **类型参数化**:在集合声明时使用尖括号`<>`来指定...
泛型引入了类型参数,例如 `<T>`,`<E>`等,这些参数代表一种未知的类型,待到实际使用时由程序员指定。泛型的主要好处包括: 1. 类型安全:在编译时就能发现潜在的类型错误,避免运行时的ClassCastException。 2. ...
泛型引入的目的是为了消除在运行时进行类型转换的需要,同时允许在设计时就对数据类型进行约束,从而提高代码的可读性和可维护性。 在Java中,集合框架包括List、Set、Queue等接口以及ArrayList、LinkedList、...
然而,随着Java 5的发布,泛型引入到Java语言中,使得我们能够更好地控制类型,并且在编译时就能捕获潜在的类型错误。 泛型的引入允许我们在创建`Hashtable`实例时指定键和值的类型。例如,如果你想要一个存储`...
8. 泛型集合:泛型引入后,Java 集合框架得到了极大的增强。使用泛型集合,可以避免在添加、删除和访问元素时出现 ClassCastException。 9. 泛型和多态:泛型可以与多态结合使用,使代码更加灵活。例如,一个接受 `...
在泛型引入后,使用泛型集合如List和Dictionary, TValue>成为首选,因为它们具有更好的类型安全性。例如,List用于存储同类型的元素序列,而Dictionary, TValue>则用于存储键值对。在ASP.NET Web开发中,集合常用于...
泛型引入后,集合可以直接指定其元素类型,编译器会在编译时检查类型一致性,确保类型安全。 在NetBeans IDE 4.0或更高版本中,你可以通过以下步骤体验泛型的使用: 1. 首先,确保安装了JDK 5.0或更高版本。如果你...
- 泛型引入了类型参数的概念,例如 `<T>`,其中 `T` 是一个占位符,代表任意类型。 - 使用泛型可以确保在编译时进行类型检查,避免运行时错误。 - 泛型方法允许我们在方法定义中使用类型参数,使方法能够处理多种...
泛型引入的主要目的是为了提高代码的重用性和减少类型转换的麻烦,同时增加了编译时的类型安全性。 在Java中,泛型主要应用于类、接口和方法。在类中,泛型用于定义参数化的数据结构,例如集合(如List、Set、Map等...
泛型引入于Java 5,增强了代码的类型安全性和可读性。它们允许我们在类、接口和方法中声明参数化类型,限制可以传递给这些类型的对象类型。这样可以防止在运行时出现ClassCastException,并在编译时捕获类型错误。...
泛型引入后,我们可以通过在类定义中添加尖括号来创建泛型类,如`class Point, T2>`。这里的`T1`和`T2`被称为类型参数,它们代表了待确定的数据类型。当我们实例化泛型类时,可以提供具体的类型,如`Point, Integer>...
泛型引入于Java 5,它的主要目标是提供编译时的类型检查,避免了类型转换的麻烦,并且能够减少运行时错误。下面我们将详细讨论泛型的基本概念和关键特性。 1. **类型参数**:在创建泛型类或泛型方法时,我们使用尖...
总之,JDK 1.5的泛型引入增强了Java的类型系统,提升了代码的清晰度和安全性。通过类型参数、类型擦除、通配符和边界等机制,泛型使得开发者能够在编译时检测类型错误,从而降低了运行时出错的可能性。在实际编程中...
- **泛型引入**:为了解决类型安全问题,Java 5引入了泛型。 - **泛型约束**:定义类型参数时可以设置边界,如 `<T extends Number>`。 - **通配符**:?表示任意类型,? extends T表示T或其子类型,? super T表示...
- 泛型引入了类型参数,使得开发者可以在不指定具体类型的情况下定义代码结构,实际使用时再根据需要指定。 2. **理解泛型** - 泛型的核心是类型参数,它是一个占位符,代表一个未知的类型。例如,`List<T>`中的`...
泛型引入于Java 5,为了解决这些问题,它允许我们在定义集合时指定元素的类型。这样可以确保在编译时进行类型检查,提高代码的可读性和安全性。例如,我们可以创建一个只存储String对象的ArrayList,如下所示: ```...
泛型引入了类型安全,使得在编译时就能检测到类型错误,而反射则允许在运行时动态地获取和操作类、接口、字段和方法的信息。 泛型是在Java 5中引入的特性,它允许在定义集合类(如List、Set、Map等)时指定元素类型...