Java JDK 版本的区别

jdk6和jdk5相比的新特性有: 
一、instrumentation 
在 Java SE 6 里面,instrumentation 包被赋予了更强大的功能:启动后的 instrument、本地代码 instrument,以及动态改变 classpath 等等。 
二、Http有所加强 
三、 Java 管理扩展(JMX) 架构及其框架,以及在 Java SE 5 中新引入的 JMX API -- java.lang.management 包 
四、JDK 6 中新增长编译器 API(JSR 199)。利用此 API,您能够在运行时调用 Java 编译器,能够编译不一样形式的源代码文件,还能够采集编译器的诊断信息。 
五、Java DB 和 JDBC 4.0 
六、对脚本语言的支持 
Java SE 6 新引入的对 JSR 223 的支持,它旨在定义一个统一的规范,使得 Java 应用程序能够经过一套固定的接口与各类脚本引擎交互,从而达到在 Java 平台上调用各类脚本语言的目的。 
七、XML API 与 Web 服务 
Java SE 6 中提供的 XML 处理框架,以及在此框架之上结合注释(Annotation) 技术,所提供的强大的针对 Web 服务的支持 
要详细的能够参看: 
http://www.ibm.com/developerworks/cn/java/j-lo-jse6/java

多了很多新特性 
一.Instrumentation 
利用 Java 代码,即 java.lang.instrument 作动态 Instrumentation 是 Java SE 5 的新特性,它把 Java 的 instrument 功能从本地代码中解放出来,使之能够用 Java 代码的方式解决问题。在 Java SE 6 里面,instrumentation 包被赋予了更强大的功能:启动后的 instrument、本地代码(native code)instrument,以及动态改变 classpath 等等。在 Java SE 5 当中,开发者只能在 premain 当中施展想象力,所做的 Instrumentation 也仅限与 main 函数执行前,这样的方式存在必定的局限性。在 Java SE 6 的 Instrumentation 当中,有一个跟 premain“并驾齐驱”的“agentmain”方法,能够在 main 函数开始运行以后再运行。 
2、Http 
在 Java SE 6 当中,围绕着 HTTP 协议出现了不少实用的新特性:NTLM 认证提供了一种 Window 平台下较为安全的认证机制;JDK 当中提供了一个轻量级的 HTTP 服务器;提供了较为完善的 HTTP Cookie 管理功能;更为实用的 NetworkInterface;DNS 域名的国际化支持等等。 
HTTP Cookie管理能够应用客户操做临时变量的保存,如查询条件,当前状态等 
3、JMX与系统管理 
管理系统的构架 
图 1. 管理系统构架 
上图分析了管理系统的基本构架模式。其中 Agent / SubAgent 起到的就是翻译的做用:把 IT 资源报告的消息以管理系统能理解的方式传送出去。 
也许读者有会问,为何须要 Agent 和 SubAgent 两层体系呢?这里有两个现实的缘由: 
管理系统通常是一个中央控制的控制软件,而 SubAgent 直接监控一些资源,每每和这些资源分布在同一物理位置。当这些 SubAgent 把状态信息传输到管理系统或者传达管理系统的控制指令的时候,须要提供一些网络传输的功能。 
管理系统的消息是有必定规范的,消息的翻译自己是件复杂而枯燥的事情。 
通常来讲,管理系统会将同一物理分布或者功能相似的 SubAgent 分组成一组,由一个共用的 Agent 加以管理。在这个 Agent 里封装了 1 和 2 的功能。 
JMX 和管理系统 
JMX 既是 Java 管理系统的一个标准,一个规范,也是一个接口,一个框架。图 2 展现了 JMX 的基本架构。 
图 2. JMX 构架 
和其它的资源系统同样,JMX 是管理系统和资源之间的一个接口,它定义了管理系统和资源之间交互的标准。javax.management.MBeanServer 实现了 Agent 的功能,以标准的方式给出了管理系统访问 JMX 框架的接口。而 javax.management.MBeans 实现了 SubAgent 的功能,以标准的方式给出了 JMX 框架访问资源的接口。而从类库的层次上看,JMX 包括了核心类库 java.lang.management 和 javax.management 包。java.lang.management 包提供了基本的 VM 监控功能,而 javax.management 包则向用户提供了扩展功能。 
JMX帮助开发者监控JVM的信息 
4、编辑器API 
JDK 6 提供了在运行时调用编译器的 API。在传统的 JSP 技术中,服务器处理 JSP 一般须要进行下面 6 个步骤: 
分析 JSP 代码; 
生成 Java 代码; 
将 Java 代码写入存储器; 
启动另一个进程并运行编译器编译 Java 代码; 
将类文件写入存储器; 
服务器读入类文件并运行; 
但若是采用运行时编译,能够同时简化步骤 4 和 5,节约新进程的开销和写入存储器的输出开销,提升系统效率。实际上,在 JDK 5 中,Sun 也提供了调用编译器的编程接口。然而不一样的是,老版本的编程接口并非标准 API 的一部分,而是做为 Sun 的专有实现提供的,而新版则带来了标准化的优势。 
新 API 的第二个新特性是能够编译抽象文件,理论上是任何形式的对象 —— 只要该对象实现了特定的接口。有了这个特性,上述例子中的步骤 3 也能够省略。整个 JSP 的编译运行在一个进程中完成,同时消除额外的输入输出操做。 
第三个新特性是能够收集编译时的诊断信息。做为对前两个新特性的补充,它可使开发人员轻松的输出必要的编译错误或者是警告信息,从而省去了不少重定向的麻烦 
5、Java DB 与jdbc4.0 
新安装了 JDK 6 的程序员们也许会发现,除了传统的 bin、jre 等目录,JDK 6 新增了一个名为 db 的目录。这即是 Java 6 的新成员:Java DB。这是一个纯 Java 实现、开源的数据库管理系统(DBMS),源于 Apache 软件基金会(ASF)名下的项目 Derby。 
从 Java 6 开始,应用程序再也不须要显式地加载驱动程序了,DriverManager 开始可以自动地承担这项任务。 
6、对脚本语言的支持 
Java SE 6 引入了对 Java Specification Request(JSR)223 的支持,JSR 223 旨在定义一个统一的规范,使得 Java 应用程序能够经过一套固定的接口与各类脚本引擎交互,从而达到在 Java 平台上调用各类脚本语言的目的。 
Java 脚本 API 为开发者提供了以下功能: 
获取脚本程序输入,经过脚本引擎运行脚本并返回运行结果,这是最核心的接口。 
发现脚本引擎,查询脚本引擎信息。 
经过脚本引擎的运行上下文在脚本和 Java 平台间交换数据。 
经过 Java 应用程序调用脚本函数。 
7、XML API 与 Web 服务程序员

1.4与1.5区别数据库

1 泛型 
2 自动装箱/拆箱 
3 for-each 
4 static import 
5 变长参数编程

1. 泛型 1.4以前 java util包中容器类,装的是Object对象,你要装特定的类型能够,但要强制转换,这可能致使运行时错误. 
例:原来ArrayList list=new ArrayList(); 
list.add(new Integer(3)); 
list.add(new Integer(4)); 
int i=((Integer)(list.get(0))).parseInt(); 
很麻烦 
如今ArrayListlist=new ArrayList(); 
list.add(new Integer(3)); 
list.add(new Integer(4)); 
int i=list.get(0).parseInt(); 
不用Cast,运行时错误变为编译时错误,这是进步. 
相似与C++中的摸板templete.但机理不一样. 
2 自动装箱/拆箱 
仍是刚才例子 
最后一句可改成 
int i=list.get(0); 
原始类型与对应的包装类不用显式转换,方便 
3 for-each 
循环的加强 
int a[]={........};//初始化,略 
for(int i:a) 

...... 

不用之前的i=0;i<a.length;i++ <br="">4 static import 
之前调Java.math 
Math.sqrt(); 
如今 static import java.lang.Math.sqrt; 
再 sqrt(); 
至关于你本身类里有这个方法 
5 变长参数 
int sum(int ...intlist) 

int i,sum; 
sum=0; 
for(int i=0;i<intlist.length;i++) <br="">{ 
sum+=list[i]; 

return sum; } 
有任意个参数,把他看做数组没多大区别,只要你注意别用那些过期的方法就行,如果新版本加的或有改变的方法,docs里会说的,在方法解释下面数组

jdk6.0将会有很大变化 
加强的for循环 
为了迭代集合和数组,加强的for循环提供了一个简单、兼容的语法.有两点值得一提:安全

Init表达式 
在循环中,初始化表达式只计算一次.这意味着您一般能够移除一个变量声明.在这个例子中,咱们必须建立一个整型数组来保存computeNumbers()的结果,以防止每一次循环都从新计算该方法.您能够看到,下面的代码要比上面的代码整洁一些,而且没有泄露变量numbers: 
未加强的For:服务器

int sum = 0;网络

Integer[] numbers = computeNumbers();架构

for (int i=0; i < numbers.length ; i++)框架

sum += numbers[i];

加强后的For:

int sum = 0;

for ( int number: computeNumbers() )

sum += number;

局限性 
有时须要在迭代期间访问迭代器或下标,看起来加强的for循环应该容许该操做,但事实上不是这样,请看下面的例子: 
for (int i=0; i < numbers.length ; i++) {

if (i != 0) System.out.print(",");

System.out.print(numbers[i]);

}

咱们但愿将数组中的值打印为一个用逗号分隔的清单.咱们须要知道目前是不是第一项,以便肯定是否应该打印逗号.使用加强的for循环是没法获知这种信息的.咱们须要本身保留一个下标或一个布尔值来指示是否通过了第一项. 这是另外一个例子: 
for (Iterator it = n.iterator() ; it.hasNext() ; )

if (it.next() < 0)

it.remove();

在此例中,咱们想从整数集合中删除负数项.为此,须要对迭代器调用一个方法,可是当使用加强的for 循环时,迭代器对咱们来讲是看不到的.所以,咱们只能使用Java 5以前版本的迭代方法. 顺便说一下,这里须要注意的是,因为Iterator是泛型,因此其声明是Iterator.许多人都忘记了这一点而使用了Iterator的原始格式.

注释 
注释处理是一个很大的话题.由于本文只关注核心的语言特性,因此咱们不打算涵盖它全部的可能形式和陷阱. 咱们将讨论内置的注释(SuppressWarnings,Deprecated和Override)以及通常注释处理的局限性.

Suppress Warnings 
该注释关闭了类或方法级别的编译器警告.有时候您比编译器更清楚地知道,代码必须使用一个被否决的方法或执行一些没法静态肯定是否类型安全的动做,而使用: 
@SuppressWarnings("deprecation")

public static void selfDestruct() {

Thread.currentThread().stop();

}

这多是内置注释最有用的地方.遗憾的是,1.5.0_04的javac不支持它.可是1.6支持它,而且Sun正在努力将其向后移植到1.5中. 
Eclipse 3.1中支持该注释,其余IDE也可能支持它.这容许您把代码完全地从警告中解脱出来.若是在编译时出现警告,能够肯定是您刚刚把它添加进来——以帮助查看那些可能不安全的代码.随着泛型的添加,它使用起来将更趁手.

Deprecated 
遗憾的是,Deprecated没那么有用.它原本旨在替换@deprecated javadoc标签,可是因为它不包含任何字段,因此也就没有方法来建议deprecated类或方法的用户应该使用什么作为替代品.大多数用法都同时须要javadoc标签和这个注释.

Override 
Override表示,它所注释的方法应该重写超类中具备相同签名的方法: 
@Override

public int hashCode() {

...

}

看上面的例子,若是没有在hashCode中将"C"大写,在编译时不会出现错误,可是在运行时将没法像指望的那样调用该方法.经过添加Override标签,编译器会提示它是否真正地执行了重写. 
在超类发生改变的状况中,这也颇有帮助.若是向该方法中添加一个新参数,并且方法自己也被重命名了,那么子类将忽然不能编译,由于它再也不重写超类的任何东西.

其它注释 
注释在其余场景中很是有用.当不是直接修改行为而是加强行为时,特别是在添加样板代码的状况下,注释在诸如EJB和Web services这样的框架中运行得很是好. 
注释不能用作预处理器.Sun的设计特别预防了彻底由于注释而修改类的字节码.这样能够正确地理解该语言的成果,并且IDE之类的工具也能够执行深刻的代码分析和重构之类的功能. 
注释不是银弹.第一次遇到的时候,人们试图尝试各类技巧.请看下面这个从别人那里得到的建议: 
public class Foo {

@Property

private int bar;

}

其思想是为私有字段bar自动建立getter和setter方法.遗憾的是,这个想法有两个失败之处:1)它不能运行,2)它使代码难以阅读和处理. 它是没法实现的,由于前面已经提到了,Sun特别阻止了对出现注释的类进行修改. 
即便是可能的,它也不是一个好主意,由于它使代码可读性差.第一次看到这段代码的人会不知道该注释建立了方法.此外,若是未来您须要在这些方法内部执行一些操做,注释也是没用的. 总之,不要试图用注释去作那些常规代码能够完成的事情.

枚举 
enum很是像public static final int声明,后者做为枚举值已经使用了不少年.对int所作的最大也是最明显的改进是类型安全——您不能错误地用枚举的一种类型代替另外一种类型,这一点和int不一样,全部的int对编译器来讲都是同样的.除去极少数例外的状况,一般都应该用enum实例替换所有的枚举风格的int结构. 
枚举提供了一些附加的特性.EnumMap和EnumSet这两个实用类是专门为枚举优化的标准集合实现.若是知道集合只包含枚举类型,那么应该使用这些专门的集合来代替HashMap或HashSet. 
大部分状况下,可使用enum对代码中的全部public static final int作插入替换.它们是可比的,而且能够静态导入,因此对它们的引用看起来是等同的,即便是对于内部类(或内部枚举类型).注意,比较枚举类型的时候,声明它们的指令代表了它们的顺序值.

"隐藏的"静态方法 
两个静态方法出如今全部枚举类型声明中.由于它们是枚举子类上的静态方法,而不是Enum自己的方法,因此它们在java.lang.Enum的javadoc中没有出现. 
第一个是values(),返回一个枚举类型全部可能值的数组. 
第二个是valueOf(),为提供的字符串返回一个枚举类型,该枚举类型必须精确地匹配源代码声明. 
方法 
关于枚举类型,咱们最喜欢的一个方面是它能够有方法.过去您可能须要编写一些代码,对public static final int进行转换,把它从数据库类型转换为JDBC URL.而如今则可让枚举类型自己带一个整理代码的方法.下面就是一个例子,包括DatabaseType枚举类型的抽象方法以及每一个枚举实例中提供的实现: 
public enum DatabaseType {

ORACLE {

public String getJdbcUrl() {...}

},

MYSQL {

public String getJdbcUrl() {...}

};

public abstract String getJdbcUrl();

}

如今枚举类型能够直接提供它的实用方法.例如:

DatabaseType dbType = ...; 
String jdbcURL = dbType.getJdbcUrl();

要获取URL,必须预先知道该实用方法在哪里.

可变参数(Vararg) 
正确地使用可变参数确实能够清理一些垃圾代码.典型的例子是一个带有可变的String参数个数的log方法: 
Log.log(String code)

Log.log(String code, String arg)

Log.log(String code, String arg1, String arg2)

Log.log(String code, String[] args)

当讨论可变参数时,比较有趣的是,若是用新的可变参数替换前四个例子,将是兼容的: 
Log.log(String code, String... args) 
全部的可变参数都是源兼容的——那就是说,若是从新编译log()方法的全部调用程序,能够直接替换所有的四个方法.然而,若是须要向后的二进制兼容性,那么就须要舍去前三个方法.只有最后那个带一个字符串数组参数的方法等效于可变参数版本,所以能够被可变参数版本替换.

类型强制转换 
若是但愿调用程序了解应该使用哪一种类型的参数,那么应该避免用可变参数进行类型强制转换.看下面这个例子,第一项但愿是String,第二项但愿是Exception: 
Log.log(Object... objects) {

String message = (String)objects[0];

if (objects.length > 1) {

Exception e = (Exception)objects[1];

// Do something with the exception

}

}

方法签名应该以下所示,相应的可变参数分别使用String和Exception声明:

Log.log(String message, Exception e, Object... objects) {...}

不要使用可变参数破坏类型系统.须要强类型化时才可使用它.对于这个规则,PrintStream.printf()是一个有趣的例外:它提供类型信息做为本身的第一个参数,以便稍后能够接受那些类型.

协变返回 
协变返回的基本用法是用于在已知一个实现的返回类型比API更具体的时候避免进行类型强制转换.在下面这个例子中,有一个返回Animal对象的Zoo接口.咱们的实现返回一个AnimalImpl对象,可是在JDK 1.5以前,要返回一个Animal对象就必须声明.: 
public interface Zoo {

public Animal getAnimal();

}

public class ZooImpl implements Zoo {

public Animal getAnimal(){

return new AnimalImpl();

}

}

协变返回的使用替换了三个反模式:

直接字段访问.为了规避API限制,一些实现把子类直接暴露为字段:

ZooImpl._animal

另外一种形式是,在知道实现的其实是特定的子类的状况下,在调用程序中执行向下转换:

((AnimalImpl)ZooImpl.getAnimal()).implMethod();

我看到的最后一种形式是一个具体的方法,该方法用来避免由一个彻底不一样的签名所引起的问题:

ZooImpl._getAnimal();

这三种模式都有它们的问题和局限性.要么是不够整洁,要么就是暴露了没必要要的实现细节.

协变 
协变返回模式就比较整洁、安全而且易于维护,它也不须要类型强制转换或特定的方法或字段: 
public AnimalImpl getAnimal(){ 
return new AnimalImpl(); 

使用结果: 
ZooImpl.getAnimal().implMethod();

使用泛型 
咱们将从两个角度来了解泛型:使用泛型和构造泛型.咱们不讨论List、Set和Map的显而易见的用法.知道泛型集合是强大的而且应该常用就足够了. 
咱们将讨论泛型方法的使用以及编译器推断类型的方法.一般这些都不会出问题,可是当出问题时,错误信息会很是使人费解,因此须要了解如何修复这些问题.

泛型方法 
除了泛型类型,Java 5还引入了泛型方法.在这个来自java.util.Collections的例子中,构造了一个单元素列表.新的List的元素类型是根据传入方法的对象的类型来推断的: 
static List Collections.singletonList(T o)

示例用法:

public List getListOfOne() {

return Collections.singletonList(1);

}

在示例用法中,咱们传入了一个int.因此方法的返回类型就是List.编译器把T推断为Integer.这和泛型类型是不一样的,由于您一般不须要显式地指定类型参数. 
这也显示了自动装箱和泛型的相互做用.类型参数必须是引用类型:这就是为何咱们获得的是List而不是List.

不带参数的泛型方法 
emptyList()方法与泛型一块儿引入,做为java.util.Collections中EMPTY_LIST字段的类型安全置换: 
static List Collections.emptyList()

示例用法:

public List getNoIntegers() {

return Collections.emptyList();

}

与先前的例子不一样,这个方法没有参数,那么编译器如何推断T的类型呢?基本上,它将尝试使用一次参数.若是没有起做用,它再次尝试使用返回或赋值类型.在本例中,返回的是List,因此T被推断为Integer. 
若是在返回语句或赋值语句以外的位置调用泛型方法会怎么样呢?那么编译器将没法执行类型推断的第二次传送.在下面这个例子中,emptyList()是从条件运算符内部调用的: 
public List getNoIntegers() {

return x ? Collections.emptyList() : null;

}

由于编译器看不到返回上下文,也不能推断T,因此它放弃并采用Object.您将看到一个错误消息,好比:"没法将List转换为List." 
为了修复这个错误,应显式地向方法调用传递类型参数.这样,编译器就不会试图推断类型参数,就能够得到正确的结果:
return x ? Collections.emptyList() : null;

 

这种状况常常发生的另外一个地方是在方法调用中.若是一个方法带一个List参数,而且须要为那个参数调用这个传递的emptyList(),那么也须要使用这个语法.

集合以外 
这里有三个泛型类型的例子,它们不是集合,而是以一种新颖的方式使用泛型.这三个例子都来自标准的Java库:

Class 
Class在类的类型上被参数化了.这就使无需类型强制转换而构造一个newInstance成为可能. 
Comparable 
Comparable被实际的比较类型参数化.这就在compareTo()调用时提供了更强的类型化.例如,String实现Comparable.对除String以外的任何东西调用compareTo(),都会在编译时失败. 
Enum> 
Enum被枚举类型参数化.一个名为Color的枚举类型将扩展Enum.getDeclaringClass()方法返回枚举类型的类对象,在这个例子中就是一个Color对象.它与getClass()不一样,后者可能返回一个无名类.

通配符 
泛型最复杂的部分是对通配符的理解.咱们将讨论三种类型的通配符以及它们的用途. 
首先让咱们了解一下数组是如何工做的.能够从一个Integer[]为一个Number[]赋值.若是尝试把一个Float写到Number[]中,那么能够编译,但在运行时会失败,出现一个ArrayStoreException: 
Integer[] ia = new Integer[5];

Number[] na = ia;

na[0] = 0.5; // compiles, but fails at runtime

若是试图把该例直接转换成泛型,那么会在编译时失败,由于赋值是不被容许的:

List iList = new ArrayList();

List nList = iList; // not allowed

nList.add(0.5);

若是使用泛型,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException.

上限通配符 
咱们想要的是一个确切元素类型未知的列表,这一点与数组是不一样的. 
List是一个列表,其元素类型是具体类型Number. 
List是一个确切元素类型未知的列表.它是Number或其子类型.

上限 
若是咱们更新初始的例子,并赋值给List,那么如今赋值就会成功了: 
List iList = new ArrayList();

List nList = iList;

Number n = nList.get(0);

nList.add(0.5); // Not allowed

咱们能够从列表中获得Number,由于不管列表的确切元素类型是什么(Float、Integer或Number),咱们均可以把它赋值给Number. 
咱们仍然不能把浮点类型插入列表中.这会在编译时失败,由于咱们不能证实这是安全的.若是咱们想要向列表中添加浮点类型,它将破坏iList的初始类型安全——它只存储Integer. 
通配符给了咱们比数组更多的表达能力.

为何使用通配符 
在下面这个例子中,通配符用于向API的用户隐藏类型信息.在内部,Set被存储为CustomerImpl.而API的用户只知道他们正在获取一个Set,从中能够读取Customer. 
此处通配符是必需的,由于没法从Set向Set赋值: 
public class CustomerFactory {

private Set _customers;

public Set getCustomers() {

return _customers;

}

}

通配符和协变返回 
通配符的另外一种常见用法是和协变返回一块儿使用.与赋值相同的规则能够应用到协变返回上.若是但愿在重写的方法中返回一个更具体的泛型类型,声明的方法必须使用通配符: 
public interface NumberGenerator {

public List generate();

}

public class FibonacciGenerator extends NumberGenerator {

public List generate() {

...

}

}

若是要使用数组,接口能够返回Number[],而实现能够返回Integer[].

下限 
咱们所谈的主要是关于上限通配符的.还有一个下限通配符.List是一个确切"元素类型"未知的列表,可是多是Mnumber,或者Number的超类型.因此它多是一个List或一个List. 
下限通配符远没有上限通配符那样常见,可是当须要它们的时候,它们就是必需的.

 

下限与上限 
List readList = new ArrayList();

Number n = readList.get(0);

List writeList = new ArrayList();

 

writeList.add(new Integer(5));

第一个是能够从中读数的列表. 
第二个是能够向其写数的列表.

无界通配符 
最后,List列表的内容能够是任何类型,并且它与List几乎相同.能够随时读取Object,可是不能向列表中写入内容.

公共API中的通配符 
总之,正如前面所说,通配符在向调用程序隐藏实现细节方面是很是重要的,但即便下限通配符看起来是提供只读访问,因为remove(int position)之类的非泛型方法,它们也并不是如此.若是您想要一个真正不变的集合,可使用java.util.Collection上的方法,好比unmodifiableList(). 
编写API的时候要记得通配符.一般,在传递泛型类型时,应该尝试使用通配符.它使更多的调用程序能够访问API. 
经过接收List而不是List,下面的方法能够由许多不一样类型的列表调用: 
void removeNegatives(List list);

构造泛型类型 
如今咱们将讨论构造本身的泛型类型.咱们将展现一些例子,其中经过使用泛型能够提升类型安全性,咱们还将讨论一些实现泛型类型时的常见问题.

集合风格(Collection-like)的函数 
第一个泛型类的例子是一个集合风格的例子.Pair有两个类型参数,并且字段是类型的实例: 
public final class Pair<a,b> {

public final A first;

public final B second;

public Pair(A first, B second) {

this.first = first;

this.second = second;

}

}

这使从方法返回两个项而无需为每一个两种类型的组合编写专用的类成为可能.另外一种方法是返回Object[],而这样是类型不安全或者不整洁的. 
在下面的用法中,咱们从方法返回一个File和一个Boolean.方法的客户端能够直接使用字段而无需类型强制转换: 
public Pair<file,boolean> getFileAndWriteStatus(String path){

// create file and status

return new Pair<file,boolean>(file, status);

}

Pair<file,boolean> result = getFileAndWriteStatus("...");

File f = result.first;

boolean writeable = result.second;

集合以外 
在下面这个例子中,泛型被用于附加的编译时安全性.经过把DBFactory类参数化为所建立的Peer类型,您其实是在强制Factory子类返回一个Peer的特定子类型: 
public abstract class DBFactory {

protected abstract T createEmptyPeer();

public List get(String constraint) {

List peers = new ArrayList();

// database magic

return peers;

}

}

经过实现DBFactory,CustomerFactory必须从createEmptyPeer()返回一个Customer:

public class CustomerFactory extends DBFactory{

public Customer createEmptyPeer() {

return new Customer();

}

}

泛型方法 
无论想要对参数之间仍是参数与返回类型之间的泛型类型施加约束,均可以使用泛型方法: 
例如,若是编写的反转函数是在位置上反转,那么可能不须要泛型方法.然而,若是但愿反转返回一个新的List,那么可能会但愿新List的元素类型与传入的List的类型相同.在这种状况下,就须要一个泛型方法:

List reverse(List list)

具体化 
当实现一个泛型类时,您可能想要构造一个数组T[].由于泛型是经过擦除(erasure)实现的,因此这是不容许的. 
您能够尝试把Object[]强制转换为T[].但这是不安全的.

具体化解决方案 
按照泛型教程的惯例,解决方案使用的是"类型令牌",经过向构造函数添加一个Class参数,能够强制客户端为类的类型参数提供正确的类对象: 
public class ArrayExample {

private Class clazz;

public ArrayExample(Class clazz) {

this.clazz = clazz;

}

public T[] getArray(int size) {

return (T[])Array.newInstance(clazz, size);

}

} 为了构造ArrayExample,客户端必须把String.class传递给构造函数,由于String.class的类型是Class. 拥有类对象使构造一个具备正确元素类型的数组成为可能

相关文章
相关标签/搜索