Java泛型应用研究_伍德鹏 (1)
Java泛型(泛型接口、泛型类、泛型方法)

Java泛型(泛型接⼝、泛型类、泛型⽅法)转载转载出处:泛型接⼝:定义⼀个泛型接⼝:通过类去实现这个泛型接⼝的时候指定泛型T的具体类型。
指定具体类型为Integer:指定具体类型为String:指定具体类型为⼀个⾃定义的对象:泛型类:在编译器,是⽆法知道K和V具体是什么类型,只有在运⾏时才会真正根据类型来构造和分配内存。
泛型⽅法:引⽤其他⼈写的,觉得不错:定义泛型⽅法时,必须在返回值前边加⼀个<T>,来声明这是⼀个泛型⽅法,持有⼀个泛型T,然后才可以⽤泛型T作为⽅法的返回值。
Class<T>的作⽤就是指明泛型的具体类型,⽽Class<T>类型的变量c,可以⽤来创建泛型类的对象。
为什么要⽤变量c来创建对象呢?既然是泛型⽅法,就代表着我们不知道具体的类型是什么,也不知道构造⽅法如何,因此没有办法去new⼀个对象,但可以利⽤变量c的newInstance⽅法去创建对象,也就是利⽤反射创建对象。
泛型⽅法要求的参数是Class<T>类型,⽽Class.forName()⽅法的返回值也是Class<T>,因此可以⽤Class.forName()作为参数。
其中,forName()⽅法中的参数是何种类型,返回的Class<T>就是何种类型。
在本例中,forName()⽅法中传⼊的是User类的完整路径,因此返回的是Class<User>类型的对象,因此调⽤泛型⽅法时,变量c的类型就是Class<User>,因此泛型⽅法中的泛型T就被指明为User,因此变量obj的类型为User。
当然,泛型⽅法不是仅仅可以有⼀个参数Class<T>,可以根据需要添加其他参数。
为什么要使⽤泛型⽅法呢?因为泛型类要在实例化的时候就指明类型,如果想换⼀种类型,不得不重新new⼀次,可能不够灵活;⽽泛型⽅法可以在调⽤的时候指明类型,更加灵活。
Java的泛型详解(一)

Java的泛型详解(⼀)Java的泛型详解泛型的好处编写的代码可以被不同类型的对象所重⽤。
因为上⾯的⼀个优点,泛型也可以减少代码的编写。
泛型的使⽤简单泛型类public class Pair<T> {private T first;private T second;public Pair() {first = null;second = null;}public Pair(T first, T second){this.first = first;this.second = second;}public T getFirst(){return first;}public T getSecond(){return second;}public void setFirst(T first) {this.first = first;}public void setSecond(T second) {this.second = second;}}上⾯例⼦可以看出泛型变量为T;⽤尖括号(<>)括起来,并放在类名后⾯;泛型还可以定义多个类型变量⽐如上⾯的例⼦ first和second不同的类型:public class Pair<T, U> {....}注: 类型变量的定义需要⼀定的规范:(1) 类型变量使⽤⼤写形式,并且要⽐较短;(2)常见的类型变量特别代表⼀些意义:变量E 表⽰集合类型,K和V表⽰关键字和值的类型;T、U、S表⽰任意类型;类定义的类型变量可以作为⽅法的返回类型或者局部变量的类型;例如: private T first;⽤具体的类型替换类型变量就可以实例化泛型类型;例如: Pair<String> 代表将上述所有的T 都替换成了String由此可见泛型类是可以看作普通类的⼯⼚泛型⽅法我们应该如何定义⼀个泛型⽅法呢?泛型的⽅法可以定义在泛型类,也可以定义在普通类,那如果定义在普通类需要有⼀个尖括号加类型来指定这个泛型⽅法具体的类型;public class TestUtils {public static <T> T getMiddle(T... a){return a[a.length / 2];}}类型变量放在修饰符(static)和返回类型的中间;当你调⽤上⾯的⽅法的时候只需要在⽅法名前⾯的尖括号放⼊具体的类型即可;String middle = TestUtils.<String>getMiddle("a", "b", "c");如果上图这种情况其实可以省略,因为编译器能够推断出调⽤的⽅法⼀定是String,所以下⾯这种调⽤也是可以的;String middle = TestUtils.getMiddle("a", "b", "c");但是如果是以下调⽤可能会有问题:如图:可以看到变意思没有办法确定这⾥的类型,因为此时我们⼊参传递了⼀个Double3.14 两个Integer1729 和0 编译器认为这三个不属于同⼀个类型;此时有⼀种解决办法就是把整型写成Double类型类型变量的限定有时候我们不能⽆限制的让使⽤者传递任意的类型,我们需要对我们泛型的⽅法进⾏限定传递变量,⽐如如下例⼦计算数组中最下的元素这个时候是⽆法编译通过的,且编译器会报错因为我们的编译器不能确定你这个T 类型是否有compareTo这个函数,所以这么能让编译器相信我们这个T是⼀定会有compareTo呢?我们可以这么写<T extends Comparable> 这⾥的意思是T⼀定是继承Comparable的类因为Comparable是⼀定有compareTo这个⽅法,所以T⼀定有compareTo⽅法,于是编译器就不会报错了因为加了限定那么min这个⽅法也只有继承了Comparable的类才可以调⽤;如果要限定⽅法的泛型继承多个类可以加extends 关键字并⽤&分割如:T extends Comparable & Serializable限定类型是⽤&分割的,逗号来分割多个类型变量<T extends Comparable & Serializable , U extends Comparable>类型擦除不论什么时候定义⼀个泛型类型,虚拟机都会提供⼀个相应的原始类型(raw type)。
跟我学Java泛型技术及应用实例——Java泛型技术在Java集合中的应用示例

直接报错。而当我们从集合中取出成员元素时直接取出即可,不用进行类型转换,因为已经 规定了里面存放的只能是某种类型。
当然,在集合中除了可以存入定义的泛型类型的对象实例之外,也还可以存入泛型类型 子类的对象实例。
在 Java 语言中将集合设计为 泛型,如下示图为 JDK API 中的 Collection 集合接口的定 义:
增加了泛型支持后的 Java 集合,完全可以记住集合中各个成员元素的数据类型,并可以 在编译时检查集合中元素的类型。即解决一些安全问题;同时还可以让代码变得更加简洁。
杨教授工作室,版权所有,盗版必究, 1/10 页
杨教授工作室,版权所有,盗版必究, 3/10 页
杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料
则可以传递该接口的实现类。下面的示例是将 E 设置为 Number 类型: List<Number> numberList= new ArrayList<Number>(); numberList.add(2.0); numberList.add(2); 而下面的示例是将 E 设置为 String 类型:List<String> myList;那工作室 精心创作的优秀程序员 职业提升必读系列资料
2、不采用泛型的集合元素的应用示例 java.util.List oneList=new java.util.ArrayList(); oneList.add("1"); /** 在使用时通过强制类型转换获得正确的值 */ oneList.add(new Integer(2)); String oneElement=(String)oneList.get(0); /** 此时将会出现转换错误而产生异常抛出 */ System.out.println("不采用泛型的集合元素:"+oneElement); String twoElement=(String)oneList.get(1); System.out.println("不采用泛型的集合元素:"+twoElement);
Java语言泛型编程最佳实践讲解

Java语言泛型编程最佳实践讲解泛型在Java语言中是一项非常重要的特性,它提供了类型安全和重用性,使得代码更具可读性和可维护性。
本文将介绍Java语言泛型编程的最佳实践,帮助读者更好地理解和运用泛型。
一、为什么使用泛型?使用泛型的主要目的是增加代码的可读性和类型安全性。
通过泛型,我们可以在编译期间检查类型的正确性,并在运行时避免类型转换错误。
泛型还可以提供代码重用性,避免代码冗余。
因此,使用泛型可以帮助我们编写更优雅、更健壮的代码。
二、泛型的基本用法1. 类型参数在使用泛型时,我们需要使用类型参数来指定具体的类型。
类型参数使用尖括号(<>)表示,放在类名或方法名后面。
例如,下面是一个泛型类的定义:```javapublic class Box<T> {private T value;public T getValue() {return value;}public void setValue(T value) {this.value = value;}}```在上述代码中,`T`是一个类型参数,可以在类的内部表示任意类型。
我们可以通过`T`来定义成员变量、方法参数、返回值等。
2. 类型通配符有时,我们需要在泛型中处理多个不同类型的对象。
这时,可以使用通配符(`?`)来表示任意类型。
例如,我们可以声明一个接收任意类型参数的方法:```javapublic void process(Box<?> box) {// 处理逻辑}```在上述代码中,`Box<?>`表示一个可以处理任意类型参数的`Box`对象。
3. 泛型方法除了在类中使用泛型,我们还可以在方法中使用泛型。
使用泛型方法可以使方法更通用、更具灵活性。
例如,下面是一个泛型方法的定义:```javapublic <T> T getValue(Box<T> box) {return box.getValue();}```在上述代码中,`<T>`表示一个类型参数,它可以在方法内部表示任意类型。
java 泛型的用法

java 泛型的用法摘要:1.泛型的概念2.泛型的优点3.泛型类型参数4.泛型擦除5.泛型使用实例正文:泛型是Java 中一种强大的功能,它允许我们编写可以处理不同类型的代码,从而提高代码的复用性和类型安全性。
泛型的优点在于它可以让我们的代码更加灵活,不需要针对每个类型都编写特定的方法或类。
在Java 中,泛型是通过在类型后面跟上尖括号<>,然后跟一个或多个类型参数来定义的。
这些类型参数通常使用大写字母表示,如T、E、K、V 等。
类型参数可以有一个或多个,用逗号分隔。
当我们使用泛型时,Java 编译器会进行泛型擦除。
这意味着在编译时,泛型类型参数将被替换为实际的类型。
这样一来,运行时的类型信息就与使用泛型之前一样。
这种擦除可以防止在运行时出现类型不匹配的问题。
下面我们通过一个简单的例子来说明泛型的用法。
假设我们有一个Box 类,用于存储和操作不同类型的对象。
我们可以使用泛型来定义这个类,从而使其可以处理多种类型的数据。
```javapublic class Box<T> {private T content;public Box() {}public Box(T content) {this.content = content;}public T getContent() {return content;}public void setContent(T content) {this.content = content;}}```在上面的代码中,我们定义了一个名为Box 的泛型类,泛型类型参数为T。
Box 类包含一个泛型类型的成员变量content,以及相应的构造函数、getter 和setter 方法。
我们可以使用这个泛型Box 类来存储和操作不同类型的数据,例如:```javaBox<String> stringBox = new Box<>();stringBox.setContent("Hello, world!");String stringContent = stringBox.getContent();System.out.println(stringContent);Box<Integer> integerBox = new Box<>();integerBox.setContent(42);int integerContent = integerBox.getContent();System.out.println(integerContent);```通过使用泛型,我们可以在编译时检查类型安全,并在运行时获得正确的类型信息。
Java泛型(参数化类型)

Java泛型(参数化类型)Java 泛型Java 泛型(generics)是 JDK 5 中引⼊的⼀个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到⾮法的类型。
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为⼀个参数。
⼀. 泛型概念的提出(为什么需要泛型)?⾸先,我们看下下⾯这段简短的代码:public class Test{public static void main(String[] args) {List list = new ArrayList();list.add("cat");list.add(20);for (int i = 0; i < list.size(); i++) {String name = (String) list.get(i); // 标记 1System.out.println("name:" + name);}}}我们发现此段代码编译期是正常的,但会在运⾏期标记1处出现“ng.ClassCastException”异常。
在如上的编码过程中,我们发现主要存在两个问题:1.当我们将⼀个对象放⼊集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运⾏时类型任然为其本⾝类型。
2.因此,//1处取出集合元素时需要⼈为的强制类型转化到具体的⽬标类型,且很容易出现“ng.ClassCastException”异常。
那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运⾏时就不会出现“ng.ClassCastException”异常呢?答案就是使⽤泛型。
⼆.什么是泛型?简单点说就是参数类型可变化,直接上例⼦:public class Test{public static void main(String[] args) {//List list = new ArrayList();//list.add("cat");//list.add(20);List<String> list = new ArrayList<String>();list.add("cat");list.add("dog");//list.add(50); // 标记 1 提⽰编译错误for (int i = 0; i < list.size(); i++) {String name = (String) list.get(i);System.out.println("name:" + name);}}}采⽤泛型写法后,在//1处想加⼊⼀个Integer类型的对象时会出现编译错误,通过List<String>,直接限定了list集合中只能含有String类型的元素,从⽽在//2处⽆须进⾏强制类型转换,因为此时,集合能够记住元素的类型信息,编译器已经能够确认它是String类型了。
java 泛型的用法
java 泛型的用法【原创实用版】目录1.Java 泛型的概念2.Java 泛型的好处3.Java 泛型的使用方法4.Java 泛型的注意事项正文【1.Java 泛型的概念】Java 泛型是 Java 语言中一种重要的特性,它允许程序员在编译时检查类型安全,从而提高代码的可靠性和可维护性。
泛型是一种抽象概念,它允许我们创建一组具有相同类型约束的类或方法。
在 Java 中,泛型通常用尖括号(<T>)表示,其中 T 是类型参数。
【2.Java 泛型的好处】Java 泛型的主要优点是类型安全和代码重用。
类型安全意味着在编译时检查类型,从而减少运行时的错误。
代码重用指的是使用泛型可以创建一组具有相同类型约束的类或方法,从而减少重复代码。
【3.Java 泛型的使用方法】要使用 Java 泛型,首先需要创建一个泛型类或方法。
以下是一些使用泛型的示例:1) 创建泛型类```javapublic class Box<T> {private T content;public Box() {}public Box(T content) {this.content = content;}public T getContent() {return content;}public void setContent(T content) {this.content = content;}}```2) 创建泛型方法```javapublic class GenericsExample {public static <T> void printList(List<T> list) { for (T item : list) {System.out.println(item);}}public static void main(String[] args) {List<String> stringList = new ArrayList<>();stringList.add("Hello");stringList.add("World");printList(stringList);}}```【4.Java 泛型的注意事项】在使用 Java 泛型时,需要注意以下几点:1) 泛型擦除:Java 泛型在运行时会被擦除,即类型参数会被替换为实际类型。
java中泛型的作用
java中泛型的作用泛型是Java语言的一项强大特性,它允许我们在定义类、接口、方法等时使用类型参数,从而使得代码更加灵活和可复用。
泛型的作用主要体现在以下几个方面:1.类型安全:泛型提供了一种编译时的类型检查机制,可以在编译阶段捕获一些类型错误。
通过使用泛型,我们可以在编译时检查参数类型是否匹配,避免了在运行时可能产生的类型转换异常。
2.代码复用:使用泛型可以编写更加通用的代码,提高代码的可复用性。
通过定义泛型类或泛型方法,我们可以将相似代码逻辑抽象出来,以适用于不同的类型,从而减少重复编写代码的工作量。
3. 集合类的类型安全:泛型集合类(如ArrayList、HashSet等)可以指定存储的元素类型,使得集合中的元素都是指定类型。
这样可以在编译时就避免了将错误类型的对象存入集合的问题,并且在读取集合中的元素时可以直接获取到正确类型的对象,避免了类型转换的繁琐与风险。
4. 简化代码:在没有泛型之前,我们可能需要编写各种类型的容器类,如IntList、StringList等,用于存储不同类型的元素。
而有了泛型,我们可以使用通用的容器类List,通过指定泛型参数的方式来存储不同类型的元素,从而大大简化了代码结构。
5.提高性能:使用泛型可以避免一些不必要的类型转换,从而提高程序的执行效率。
在编译时确定了泛型类型后,编译器会自动插入类型转换的代码,避免了动态类型检查所带来的性能损失。
6.编写更安全的API:通过使用泛型,我们可以将一些类型相关的约定和规范编码到API中,从而可以在编译时强制执行这些约定,提高代码的安全性和可靠性。
7.代码逻辑清晰:泛型可以使代码更具可读性和可维护性。
通过使用泛型,我们可以在编程时直观地表达出代码逻辑的意图,从而使代码更加清晰明了。
总之,泛型是Java语言中一项非常重要的特性,它提供了更高层次的抽象和灵活性,使得我们可以编写更加通用、类型安全且可复用的代码。
通过正确地使用泛型,我们可以提高代码的质量和可维护性,并且更容易适应未来的需求变化。
java 泛型用法
java 泛型用法
Java泛型是指在编写Java程序时,使用泛型类型的技术。
泛型类型是指能够允许在代码中使用不同类型的对象。
Java泛型允许我们在编译时检查我们的代码,以确保类型的安全性,从而避免了运行时类型转换错误。
Java泛型的用法包括以下几种:
1. 泛型类
Java泛型类是一种通用类,可以用来创建其他类的对象。
泛型类可以被定义为一个或多个参数化类型,这些参数化类型被称为类型参数。
使用泛型类时,需要在实例化时指定类型参数。
2. 泛型方法
Java泛型方法是一种通用方法,可以在调用时接受不同类型的参数。
泛型方法可以被定义为一个或多个参数化类型,这些参数化类型被称为类型参数。
使用泛型方法时,需要在调用时指定类型参数。
3. 泛型接口
Java泛型接口是一种通用接口,可以用来创建其他接口的实现。
泛型接口可以被定义为一个或多个参数化类型,这些参数化类型被称为类型参数。
使用泛型接口时,需要在实现时指定类型参数。
4. 通配符
Java泛型的通配符指的是一种可以用来匹配任何类型的占位符。
通配符用?来表示,可以被用来定义泛型类型、方法或接口的参数或返回值类型。
5. 类型边界
Java泛型的类型边界指的是限制泛型类型参数的范围。
类型边界可以被用来定义泛型类型、方法或接口的参数或返回值类型。
通过类型边界,可以限制泛型参数的类型必须是某个类或接口的子类或实现类。
以上是Java泛型的主要用法,掌握这些用法可以有效提高Java 编程效率,以及提高代码的可读性和可维护性。
Java 中泛型的分析
Java 中泛型的分析Java泛型(generics)是JDK 5中引入的一个新特性,允许在定义类和接口的时候使用类型参数(type parameter)。
声明的类型参数在使用时用具体的类型来替换。
泛型最主要的应用是在JDK 5中的新集合类框架中。
对于泛型概念的引入,开发社区的观点是褒贬不一。
从好的方面来说,泛型的引入可以解决之前的集合类框架在使用过程中通常会出现的运行时刻类型错误,因为编译器可以在编译时刻就发现很多明显的错误。
而从不好的地方来说,为了保证与旧有版本的兼容性,Java泛型的实现上存在着一些不够优雅的地方。
当然这也是任何有历史的编程语言所需要承担的历史包袱。
后续的版本更新会为早期的设计缺陷所累。
开发人员在使用泛型的时候,很容易根据自己的直觉而犯一些错误。
比如一个方法如果接收List<Object>作为形式参数,那么如果尝试将一个List<String>的对象作为实际参数传进去,却发现无法通过编译。
虽然从直觉上来说,Object 是String的父类,这种类型转换应该是合理的。
但是实际上这会产生隐含的类型转换问题,因此编译器直接就禁止这样的行为。
本文试图对Java泛型做一个概括性的说明。
类型擦除正确理解泛型概念的首要前提是理解类型擦除(type erasure)。
Java中的泛型基本上都是在编译器这个层次来实现的。
在生成的Java字节代码中是不包含泛型中的类型信息的。
使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。
这个过程就称为类型擦除。
如在代码中定义的List<Object> 和List<String>等类型,在编译之后都会变成List。
JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。
Java编译器会在编译时尽可能的发现可能出错的地方,但是仍然无法避免在运行时刻出现类型转换异常的情况。
类型擦除也是Java的泛型实现方式与 C++模板机制实现方式之间的重要区别。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2008年第3卷第4期(总第22期)本栏目责任编辑:谢媛媛软件设计开发ComputerKnowledgeAndTechnology电脑知识与技术ISSN1009-3044ComputerKnowledgeAndTechnology电脑知识与技术Vol.3,No.4,August2008,pp.690-692E-mail:xsjl@cccc.net.cnhttp://www.dnzs.net.cnTel:+86-551-56909635690964Java泛型应用研究伍德鹏(广西机电职业技术学院计算机与信息工程系,广西南宁530007)摘要:分析非泛型的Java系统存在的数据类型转换安全问题,提出基于Java泛型的解决方案。
通过对泛型的原理分析,探讨Java泛型的实际应用。
并在此基础上,总结Java泛型的的特点。
关键词:泛型;对象包装;数据类型转换;集合中图分类号:TP393文献标识码:A文章编号:1009-3044(2008)22-690-03ResearchonJavaGenericsWUDe-peng(DepartmentofComputerScience&InformationEngineering,GuangxiTechnologicalCollegeofMachineryandElectricity,Nanning530007,China)Abstract:Thispaperanalysessecurityproblemofthedatatypeconvertinginnon-genericsJavasystemandputupthesolutionwhichbasesongenerics.Throughthegenericstheoryanalysis,studypracticalapplicationofgenericsinJava.Onthisbasis,sumupthefeatureofgenericsinJava.Keywords:generics;Objectpackaging;datatypeconverting;collection1引言Java语言的泛型是JDK1.5(JavaDevelopmentKit,Java开发工具包)版本之后引入的新特性。
在基于Java的系统开发中,经常需要频繁地对一些对象进行包装和取出。
包装操作一般通过集合来操作,即将多个对象实例加入到集合对象中管理和传递,然后在适当的时机在将这些对象实例从集合中取出并还原成原来的数据类型。
在JDK1.5以前的版本,在进行多个对象包装时,集合类一般都规定所其所容纳的对象为Object类型,即所有Java类的最高父类。
从集合里取出对象时,再根据需要进行强制类型转换,从而还原成包装前的对象的数据类型。
这样的操作过程存在有潜在的类型转换安全问题。
假设系统开发人员从一个集合里取出对象的时候无法知道包装前对象的数据类型,会导致无法完成转换或者隐含有类型转换错误。
针对这个问题,JDK1.5引入了泛型的概念,它能在创建一个Java集合时显式指定其所能容纳的数据类型,并在取出时明确告诉系统开发人员取出的对象是什么数据类型,这样避免了包装和取出的数据类型不一致,从而有效地避免代码中的潜在类型转换安全错误。
2Java泛型的原理2.1非泛型的数据类型转换存在的问题为了更深入理解Java泛型的概念,我们先来看一个没有引入泛型的例子:packagetest.generics;importJava.util.ArrayList;publicclassTestApp1{publicstaticvoidmain(String[]args){ArrayListlist=newArrayList();list.add(newInteger(1));list.add(newInteger(2));list.add(newDouble(5.23));for(inti=0;i<list.size();i++){Integertemp=(Integer)list.get(i);System.out.println(temp.intValue());}}}本例中,建立了一个ArrayList的实例,并分别把整数1、2和浮点数5.23添加给它。
然后循环遍历该ArrayList,从中取出整型值并打印到控制台上。
这个程序编译的时候并没有错误,能被编译通过,但是运行的时候JDK却抛出了如下异常:Exceptioninthread"main"Java.lang.ClassCastException:Java.lang.Double这是因为程序运行时,在循环里进行取出对象的时候,试图将Double类型转换成Integer类型,这显然是不合理的。
作为一个习惯于使用语言提供的类型安全的系统开发人员,希望这样的问题在编译期间就能被发现,而不是潜伏到运行的时刻才抛出错误,这正是泛型产生的原因。
收稿日期:2008-05-13作者简介:伍德鹏,广西机电职业技术学院计算机与信息工程系。
伍德鹏:Java泛型应用研究6912.2Java泛型的概念泛型(Generictype或者generics)是对Java语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。
类型参数是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
可以在集合框架(Collectionframework)中看到泛型的动机。
例如,Map类允许您向一个Map添加任意类的对象,即使最常见的情况是在给定映射(map)中保存某个特定类型(比如String)的对象。
2.3Java泛型的基本原理假如在程序代码中使用了泛型,即在创建一个对象集合的时刻显式指定该集合类所能容纳的对象数据类型,如下语句所示:ArrayList<Integer>list=newArrayList<Integer>();则Java编译器在编译时检查所有和ArrayList集合类相关的操作代码,这些操作代码主要包括对集合类添加对象、修改对象等。
如果类型和要求的不一致,即不属于Integer类型,程序将无法被编译通过。
这样确保往ArrayList中添加的对象是预定义的安全类型。
因为编译时已经在包装时进行了类型安全检查,在进行取出对象的时候,程序已经知道了集合里所装的对象的数据类型,所以拆包变得异常简单而且准确,只需要将对象从集合里取出,即可恢复成包装前的数据类型,无须再进行强制数据类型转换。
从泛型包装和取出对象的原理,我们可以知道,泛型对类型转换的检查不再推迟到运行时刻,而是在编译时就把这步工作完成。
这一个重要的改变使得系统开发人员能在编译阶段就能够发现系统潜在的危险,而不是等到运行的时候再发现。
3Java泛型的应用3.1基本应用从JDK1.5版本开始,引入了泛型的概念,使得系统开发人员能灵活地定义和使用和泛型相关的一些对象。
其主要应用在Jdk自带的集合框架类中。
如ArrayList、HashMap、Hashtable等集合对象。
下面举一个例子来说明泛型在这些集合类中的基本应用。
packagetest.generics;importJava.util.HashMap;publicclassTestApp2{publicstaticvoidmain(String[]args){HashMap<String,String>map=newHashMap<String,String>();map.put("key1","value1");map.put("key2","value2");for(inti=0;i<map.size();i++){Stringtemp=map.get(i);System.out.println(temp);}}}本例中,首先创建一个HashMap的实例,即容纳对象的集合。
注意在创建这个HashMap的实例时,需要同时指明该集合所容纳的数据类型为<String,String>。
这一步十分关键,是编译器进行类型安全检查的基本依据。
这里指定主键和值的数据类型均为String类型。
然后分别把两个配对值("key1","value1")和("key2","value2")加入HashMap对象中,完成了包装的功能。
创建了HashMap<String,String>这样一个对象实例,实际上就限定HashMap中能容纳的主键key和值value的数据类型都是String。
如果试图将其它数据类型加入这个HashMap对象中,如使用下面的代码:map.put(“key3”,newInteger(1));是不允许的,编译时会抛出如下错误:Themethodput(Stirng,String)inthetypeHashMap<String,String>isnotapplicableforthearguments(String,Integer)即在编译时,JDK对泛型类HashMap的包装操作进行了数据类型安全检查。
在这段代码中,它只能容纳(String,String)类型的数据,试图将(String,Integer)类型的数据加进这个HashMap对象是不适当的。
程序接着进行从集合里取出对象的操作。
注意有泛型的取出对象操作要比没有泛型的容易得多,只有简单的取出,不再需要进行强制的类型转换了。
3.2扩展应用基于Java泛型在集合中的基本应用,可以将其扩展到其他的应用场合。
一个典型的应用是使用泛型改善Java应用系统的DAO层(DataAccessObject,数据访问对象)的数据类型安全。
Hibernate是DAO层的应用较广泛的开发工具集,它是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,以便简单地完成数据库的访问操作。
但Hibernate由于Jdk的历史原因,目前没有在其框架中引入泛型。
如要查询表中的所有数据,没有泛型的代码如下:publicListfindAll(Stringhql){Queryq=session.createQuery(hql);Listlist=q.list();returnlist;}上面的例子由于没有泛型的安全检查,存在如下问题:1)此函数的调用者将无法知道函数返回值List中的对象是何种数据类型,如果试图其从List集合中取出对象元素,可能会导致类型转换错误。
2)函数调用者即使知道了集合中的对象类型,取出时还要进行一次类型的强制转换,将Object转换成具体的数据类型。
使用泛型改进后的代码如下:软件设计开发本栏目责任编辑:谢媛媛2008年第3卷第4期(总第22期)本栏目责任编辑:谢媛媛软件设计开发ComputerKnowledgeAndTechnology电脑知识与技术publicList<T>findAll(Stringhql){Queryq=session.createQuery(hql);Listlist=q.list();returnlist;}上面的例子函数要求调用者调用这个函数时,显式指出要查询的对象的数据类型,能有效解决类型安全和类型转换的问题。