Generics泛型的应用
JDK 5 中的泛型
Generics(泛型)
泛型的第一个优点是实现编译时期检查;第二个优点是在使用collection框架的时候不需要cast了。
一、先来了解一下JDK5以前是怎么处理的。
在JDK5之前的Collection框架以Object为参数,这样整个Collection框架可以变得通用,而不是对于每个数据类型都定义一个Collection。
比如,List的add方法: public boolean add(java.lang.Object element)
但是当你使用的时候,get()方法是这样声明的:
public java.lang.Object get(int index)
throws IndexOutOfBoundsException
请看下面的例子:
List stringList1 = new ArrayList();
stringList1.add("Java 5");
stringList1.add("with generics");
String s1 = (String) stringList1.get(0);
|
一切看起来ok,但是如果这样
List stringList1 = new ArrayList();
stringList1.add("Java 5");
stringList1.add(new Date());
stringList1.add("with generics");
String s1 = (String) stringList1.get(1);
|
看起来也ok,运行起来就出现
java.lang.ClassCastException: java.util.Date
二、应用泛型
正如方法可以接收参数,泛型类型也可以接收参数,这也是为什么generic type也称作 “parameterized type”。用<>(angle bracket)将参数传递给泛型。
例如:java.util.List,可以写作 List<E> myList,其中E称作类型变量。在JDK5中可以如下实例化:
List<String> myList = new ArrayList<String>();
在JDK5中,代码可以如下:
List<String> stringList2 = new ArrayList<String>();
stringList2.add("Java 5.0");
stringList2.add("with generics");
// no need for type casting
String s2 = stringList2.get(0);
System.out.println(s2.toUpperCase());
|
如果你尝试将Date()加入这个List
List<String> stringList2 = new ArrayList<String>();
stringList2.add("Java 5.0");
stringList2.add("with generics");
stringList2.add(new Date());
// no need for type casting
String s2 = stringList2.get(0);
System.out.println(s2.toUpperCase());
|
系统会提示:
The method add(String) in the type List<String> is not applicable for the arguments (Date)
比较前面JDK5之前的处理,已经实现了编译期检查,不会将错误留到运行时候。
三、比较JDK5和之前的处理
import java.util.List;
import java.util.ArrayList;
public class GenericListTest {
public static void main(String[] args) {
// in JDK 1.4
List stringList1 = new ArrayList();
stringList1.add("Java 1.0 - 5.0");
stringList1.add("without generics");
// cast to java.lang.String
String s1 = (String) stringList1.get(0);
System.out.println(s1.toUpperCase());
// now with generics in JDK 5
List<String> stringList2 = new ArrayList<String>();
stringList2.add("Java 5.0");
stringList2.add("with generics");
// no need for type casting
String s2 = stringList2.get(0);
System.out.println(s2.toUpperCase());
}
}
|
下面是一个有趣的应用:
import java.util.ArrayList;
import java.util.List;
public class ListOfListsTest {
public static void main(String[] args) {
List<String> listOfStrings = new ArrayList<String>();
listOfStrings.add("Hello again");
List<List<String>> listOfLists = new ArrayList<List<String>>();
listOfLists.add(listOfStrings);
String s = listOfLists.get(0).get(0);
System.out.println(s); // prints "Hello again"
}
}
|
四、泛型进阶
对于没有使用泛型处理的代码,在JDK5中,系统会出现编译警告,提示代码为”raw type”。
这是兼容的,如果不想看到这个信息,可以做如下处理:
1, 使用 –source 1.4 参数编译。
2, 使用@SupressWarnings(“unchecked”) annotaion
3, 升级为使用泛型
如果你声明一个泛型List<atype>,那么List的实现中,atype可以是如下类型:
1, atype的实例
2, atype子类的实例(如果atype是一个class)
3, atype的实现类的实例(如果atype是一个接口)
泛型和Java对象一样,都有自己的类型,下面两个就是完全独立,没有关系的:
List<Object> list1 = new ArrayList<Object>();
List<String> list2 = new ArrayList<String>();
虽然String是Object的子类,但是List<String>可不是List<Object>的子类。
再看下面的代码,
import java.util.ArrayList;
import java.util.List;
public class AllowedTypeTest {
public static void doIt(List<Object> l) {
}
public static void main(String[] args) {
List<String> myList = new ArrayList<String>();
// this will generate a compile error
doIt(myList);
}
}
|
系统会提示编译错误。
为了解决类似的问题,JDK5提出了通配符号(?),List<?>,这个声明意味着List可以接收任何对象。
import java.util.ArrayList;
import java.util.List;
public class WildCardTest {
public static void printList(List<?> list) {
for (Object element : list) {
System.out.println(element);
}
}
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("Hello");
list1.add("World");
printList(list1);
List<Integer> list2 = new ArrayList<Integer>();
list2.add(100);
list2.add(200);
printList(list2);
}
}
|
特别注意,如果你这样声明就不对了:
List<?> myList = new ArrayList<?>();
边界通配符 (bounded wildcards)
在泛型中,如果你有一个getAverage方法用来返回平均值,你可能要传递integer,float,double等。那么你将参数设置为List<Number>,但是由于List<Number>、List<Integer>、List<Double>是不同的类型,所以不行。我们还可以用List<?>,但是这样会降低类型安全,因为List<String>也可能发生。
JDK5推出upper bounded ,格式如下:
GenericType <? Extends uppderBoundedType>
请看下面的例子:
import java.util.ArrayList;
import java.util.List;
public class BoundedWildcardTest {
public static double getAverage(List<? extends Number> numberList)
{
double total = 0.0;
for (Number number : numberList)
total += number.doubleValue();
return total/numberList.size();
}
public static void main(String[] args) {
List<Integer> integerList = new ArrayList<Integer>();
integerList.add(3);
integerList.add(30);
integerList.add(300);
System.out.println(getAverage(integerList)); // 111.0
List<Double> doubleList = new ArrayList<Double>();
doubleList.add(3.0);
doubleList.add(33.0);
System.out.println(getAverage(doubleList)); // 18.0
}
}
|
It’s so ok
如果在main()
分享到:
相关推荐
简单泛型通常应用于容器类的设计。以无泛型的`Holder1`为例,它可以存储任何类型的对象,但这样会导致编译器无法进行有效的类型检查。引入泛型后的`Holder2`,如示例所示,通过类型参数`T`实现了对存储类型的约束,...
结合WATest这个文件名,我们可以猜测这是一个测试用例,可能是用于验证泛型应用或静态页面生成功能的正确性。具体的测试细节可能包括检查泛型类的实例化、操作是否符合预期,以及静态页面生成后的HTML内容是否正确...
本资料 "[Java泛型和集合].(Java.Generics.and.Collections).Maurice.Naftalin&Philip.Wadler.文字版" 由知名专家Maurice Naftalin和Philip Wadler编著,提供了关于这些主题的深入理解。 **Java泛型** 是自Java...
- 泛型不仅可以应用于类,还可以应用于方法。例如,可以定义一个泛型方法,使其能接受不同类型的参数并返回不同类型的值。 9. **类型推断** - 自JDK 7起,Java引入了类型推断,允许在某些情况下省略类型参数,...
环境:Windows XP Professional、JDK 1.6、Ant 1.7 说明:Java泛型的动机是为解决类型转换在编译时不报错的问题。另外由于“范型编程”(Generic Programming)的推广,于是2004年JDK 5.0引用范型标准。本例子说明...
Java 1.5引入了泛型(Generics)的概念,这是一个重要的语言特性,它允许开发者在编译时期指定集合或其他数据结构中的元素类型,从而避免了运行时期的类型转换错误。通过使用泛型,开发者可以在编程阶段就确保类型的...
泛型(Generics)是一种在编程中引入的模板机制,用于在定义数据结构或方法时创建类型参数。这些参数可以在实例化时替换为具体的类型,使得容器(如List、Set、Map等)能够存储特定类型的元素,而不是任意类型。...
泛型(Generics)是指在面向对象编程中,通过参数化类型来达到类型重用的目的。通俗地说,就是将类或方法中的某些类型定义为参数形式,在实际使用时再传入具体类型的机制。 ##### 2.2 为什么使用泛型? 1. **类型...
### 泛型(Generics) 泛型是C#中一个非常强大的特性,允许开发者创建类型安全的、可重用的组件。在给定的代码片段中,`SetListValue<T>` 方法是一个泛型方法,其中 `T` 是类型参数。这意呀着该方法可以接受任何...
### Java 泛型详解与应用 #### 一、什么是Java泛型? Java泛型(Generics)是一种在编译时确保类型安全的机制,它允许程序员编写类型安全的通用类或方法,而无需进行显式的类型转换。在Java 1.5引入泛型之前,集合...
在Java编程语言中,泛型(Generics)和方法是两个重要的概念,它们极大地提高了代码的类型安全性和可重用性。这篇博文将探讨这两个主题,并结合源码和工具进行深入解析。 首先,泛型是Java 5引入的一项重要特性,它...
2. 代码重用:泛型可以将类型参数化,使得代码可以应用于多种类型。 3. 代码简洁:泛型可以减少类型转换的代码,使得代码更加简洁。 泛型的基本概念: 1. 类型参数:泛型的核心概念是类型参数,例如 List<E> 中的 ...
在Java编程中,反射(Reflection)和泛型(Generics)是两个非常重要的特性,它们分别提供了对运行时类型信息的动态访问以及类型安全的代码编写能力。在本主题中,我们将深入探讨如何通过反射获取泛型参数,并利用...
Java泛型(Generics)是Java SE 5.0引入的一种新特性,它允许程序员在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。下面将根据给定的文件信息,深入解析Java泛型的一些核心知识点...
首先,我们来看泛型(Generics)。泛型是在Java SE 5.0引入的新特性,它允许在编译时检查类型安全,并且所有的强制类型转换都是自动和隐式的,提高了代码的重用率。泛型的基本语法是在类、接口或方法声明前加上尖...
Java开发工具包(JDK)1.5引入了一项重大改进,那就是泛型(Generics)。泛型是Java编程语言中的一个关键特性,它允许在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率。通过泛型,...