站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2SE 专题“老虎”来了 J2SE1.5新功能一览 李娟编译 天极网

“老虎”来了 J2SE1.5新功能一览 李娟编译 天极网

摘要: “老虎”来了 J2SE1.5新功能一览 李娟编译 天极网

虽然Java版本从1.0发展到1.4.2,但Java语言本身一直没有什么大的变化,只是增加了少量关键字,所以业界一直在呼吁对Java语言进行修正,以适应新的开发技术。2004年2月Sun发布了代号为“虎”的Java 2标准版( J2SE) 1.5的第一个测试版beta1,几个月后又发布了Beta2版。在这个版本中Sun对Jav语言做了许多令人振奋的革新。为了与.NET竞争,J2SE1.5在易用性上做了重大改进,引入了泛型、增强FOR循环、元数据、类似C语言的格式化输入输出、静态导入、可变参数等总共15个组件JSR(Java Specification Requests )以及由 Java 社团(Java Community Process,JCP)开发的其他将近100个重大更新。

在这个版本中有这么多令人激动的改变,也许您想尽快了解并使用这些新功能,那么来吧,本文将向你介绍这些重大的修订,这样就可以在深入学习API文档之前对J2SE 1.5有一个大体的了解。

  阅读导航

   易开发性
   J2SE1.5 Beta2发布了,Sun在这个版本中对Java语言做了重大修正;这些修正包括泛型、元数据、自动包装、增强的"for"循环、枚举类型、静态导入、类似C语言的格式输入/输出、可变参数、并发程序和更简单的RMI接口。 

   可扩展性和性能
   Sun承诺在1.5版中对可扩缩性和性能方面进行改善,它着重于启动时间和内存大小,使得高速部署应用程序变得更加容易。 

   监控和可管理性
   J2SE 1.5版提供广泛的监控和管理支持:遵守Java虚拟机的实现方法,Java管理扩展( JMX)框架和远程访问协议。

   桌面客户端
   Java桌面客户端保留了Java平台的一个关键组成部分,并且这一点成了 J2SE 1.5 中许多改进的焦点。

   其他特性
   J2SE1.5还引入了几个核心XML平台的修订版以及32位的辅助字符和新的JDBC RowSet,极大的提高了数据库应用程序的开发效率。 

  小结

  总之,Tiger是一个以开发者为中心的版本。自Java语言诞生后,Java的发展速度就像是一个起飞的火箭一样,原因就在于它触动了开发者的心灵,点燃了他们的热情。这个版本的开发依然是基于这个思想。

  我们很幸运能有机会最早接触这些语言的新特性,使用它们是一种乐趣。在现有的各种开发语言中,Java本来就是一个非常好用而且富有生产力的语言,而所有的即将到来的新特性又会大大地增强使用它的乐趣。

简化开发

  J2SE1.5 Beta2发布了,Sun在这个版本中对Java语言做了重大修正;这些修订包括泛型、元数据、自动包装、增强的"for"循环、枚举类型、静态导入、类似C语言的格式输入/输出、可变参数、并发程序和更简单的RMI接口。JSR - 201包含四个语言修改;增强的循环、枚举类型、静态导入和自动包装;JSR - 175指定了新的元数据函数、而JSR - 14描述了泛型。

  新的默认语言规范是由1.5版javac编译程序实现的,你不需要像在beta1版中那样提供-source 1.5这个选项。

  元数据

  J2SE 1.5 中的元数据特性提供这样的能力,即向 Java 类、接口、方法和字段关联附加的数据。这些附加的数据或者注释,可以被 javac 编译器或其他工具读取,并且根据不同配置,可以被保存在类文件中,也可以在运行时用 Java 反射 API 发现。

  添加元数据到Java平台中的最主要的原因是能够使开发工具和运行工具有一个共同的体系结构,以减少编程和部署所需要的成本。工具可以使用元数据信息生成附加的源代码,或者在调试的时候提供附加信息。

  在beta2中,我们很高兴地发现了一个名为apt的注释处理工具。 Apt包括一组新的映射应用程序编程接口和工作程序注解的支持体系结构。apt在映射应用程序编程接口时提供一个构造期间、基于源代码的程序结构的只读视图,来清晰地模拟它的Java程序语言的类型系统。首先,apt运行可以生成新的源代码和其它文件的注释处理程序。其次,apt可以编译原始的源文件和生成的源程序,简化了开发。更多的关于apt的信息,请参考apt指南http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html。

  下面的例子用元数据工具创建了一个调试元数据注释,然后这些元数据注释在运行时显示出来。可以想像,大部分的元数据标签形成一个标准,即一个良好规范的集合。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>import java.lang.annotation.*;
import java.lang.reflect.*;
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface debug
{
 boolean devbuild() default false;
 int counter();
}
public class MetaTest
{
 final boolean production=true;
 @debug(devbuild=production,counter=1)
 public void testMethod() { }
 public static void main(String[] args)
 {
  MetaTest mt = new MetaTest();
  try
  {
   Annotation[] a = mt.getClass().getMethod("testMethod").getAnnotations();
   for (int i=0; i<a.length ; i++)
   {
    System.out.println("a["+i+"]="+a[i]+" ");
   }
  }
  catch(NoSuchMethodException e)
  {
   System.out.println(e);
  }
 }
}</td> </tr> </table>
  使用元数据处理工具,许多重复的代码步骤可以被简化为一个简明的元数据标签。例如,当访问一个JAX-RPC服务实现的时候,所需得远程接口可以如下面的代码这样实现:

  J2SE1.5版以前

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>public interface PingIF extends Remote
{
 public void ping() throws RemoteException;
}
public class Ping implements PingIF
{
 public void ping() { }
}</td> </tr> </table>
  J2SE1.5

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>public class Ping
{
 public @remote void ping() { }
}</td> </tr> </table>
  泛型

  泛型已经为Java社团所广泛期待,现在成了J2SE 1.5版的一个组成部分。最先能看到泛型起作用的地方就是Collection API。Collection API提供了像LinkedLists, ArrayLists 和 HashMaps这样的函数,可以被不止一种的Java类型使用。接下来的示例中使用了1.4.2库和默认的javac编译方式。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>ArrayList list = new ArrayList();
list.add(0, new Integer(42));
int total = ((Integer)list.get(0)).intValue();</td> </tr> </table>
  最后一行中的 Integer 转换是泛型所要防止的强制类型转换问题的一个例子。问题是1.4.2版本中,Collection API使用Object类来保存Collection对象,这意味着在编译时不能找出任何类型匹配。问题的第一个标志信息是在运行时抛出的 ClassCastException。

  使用泛型化的Collection库编写的相同示例如下:

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = list.get(0).intValue();</td> </tr> </table>
  使用泛型应用编程接口的用户必须只使用<>符号声明在编译类型中使用的类型,不需要进行任何类型强制转换,在本例中试图向Integer集合中添加一个String对象到的操作将会在编译时被捕获。

  泛型允许 API 设计者提供这样的公共功能性:可以与多种数据类型一起使用,也可以在编译时出于类型安全对它进行检查。

  设计你们自己泛型应用程序编程接口比仅仅使用它们要复杂一些。你可以参考java.util.Collection源程序和应用编程接口指南来实现。

  基本类型的自动装箱和拆箱(Autoboxing 和 Auto-unboxing)

  象int、boolean和它们的相对应的基于Object的相应物如Integer和Boolean这样的基本数据类型互相间进行转换时,需要大量不必要的额外编码,尤其是当只是像 Collections API 这样的方法调用需要转换时更甚。

  Java基本类型的autoboxing 和 auto-unboxing 产生更加简明和易用的代码。1.5 版本让所需要的转换转变成 Integer 并转换回编译器。

  1.5版前

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = (list.get(0)).intValue();</td> </tr> </table>
  1.5版

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, 42);
int total = list.get(0);</td> </tr> </table> 增强的 for循环

  Collections API经常使用Iterator类。 Iterator类提供在 Collection 中遍历导航的机制。当在集合和数组中遍历时,新的增强的 for 循环可取代 iterator。编译器生成必要的循环代码,因为利用范型,所以不需要额外的类型转换。

  以前

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>ArrayList<Integer> list = new ArrayList<Integer>();
for (Iterator i = list.iterator(); i.hasNext();)
{
 Integer value=(Integer)i.next();
}</td> </tr> </table>
  现在

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>ArrayList<Integer> list = new ArrayList<Integer>();
for (Integer i : list)
{
  ...
}</td> </tr> </table>
  枚举类型

  当使用 static final 型常量时,该类型提供枚举的类型。如果你以前在你自己的应用程序中使用过enum标识符,那么在利用J2SE1.5进行编译时需要修改源代码。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>public enum StopLight
{
 red, amber, green
};</td> </tr> </table>
  静态导入

  静态导入特性实现了"import static",允许您从一个类引用静态常量,而不需要继承它。例如,我们添加一个组件的时候不需要每次都使用BorderLayout.CENTER,而是只引用CENTER就可以了。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>import static java.awt.BorderLayout.*;
getContentPane().add(new JPanel(), CENTER);</td> </tr> </table>
  格式化输出

  开发者现在可以选择使用printf类型的函数来生成格式化输出。这样有助于将C语言应用程序中移植到Java上,这样文本布局可以基本没有什么变化。

  大部分公用的C语言的printf的格式标识符都可以用,此外一些Java类像Date和BigInteger也有了格式化规则。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>System.out.printf("name count%n");
System.out.printf("%s %5d%n", user,total);</td> </tr> </table>
  格式化输入

  scanner应用编程接口提供了用于从系统控制台或者任何数据流读出数据的基本输入功能。下面的示例从标准输入读取一个字符串。

  如果没有数据可用的话,像next和nextInt这样的方法将阻塞。如果你需要处理更加复杂的输入,那么还有模式匹配算法,可以从java.util.Formatter类中获得。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>Scanner s= new Scanner(System.in);
String param= s.next();
int value=s.nextInt();
s.close();</td> </tr> </table>
  可变参数

  可变参数功能允许多个参数作为传入方法的参数。它只需要简单的"..."表示法,该符号用于接收参数列表的方法,并且它还被用于实现 printf 所需参数的灵活数量。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>void argtest(Object ... args)
{
 for (int i=0;i <args.length; i++) { }
}
argtest("test", "data");</td> </tr> </table>
  并行性实用程序

  并行实用程序库由Doug Lea定义在 JSR-166 中,是一个J2SE 1.5平台中公用的并发程序包的特殊版本。它提供了强大的,高级的线程构成器,包括executors(这是一个线程任务框架)、线程安全队列、Timers、锁(包括原子锁)和其他同步原语。

  著名的旗语(semaphore)是这样一个锁。semaphore和现在使用的wait的使用方式相同,用于限制对代码块的访问。Semaphore更加灵活,可以允许许多并发的线程访问,还允许在获得一个锁定之前测试它。下面的示例只使用了一个semaphore,也称二元semaphore。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>final private Semaphore s= new Semaphore(1, true);
s.acquireUninterruptibly();
//for non-blocking version use
s.acquire()try
{
 balance=balance+10; //protecte
 d value} finally
 {
  s.release();
  //return semaphore token
 }
} </td> </tr> </table>
  rmic - - RMI编译程序

  你不必再使用rmic——rmi编译程序工具——来生成远程接口程序了。动态代理的引入意味着由程序正常提供的信息可以在运行期间显示。

可扩缩性和性能

  Sun承诺在1.5版中对可扩缩性和性能方面进行改善,新的重点在于启动时间和内存大小,使得高速部署应用程序变得更加容易。

  最显著的更新是引入了在HotSpot JVM中共享数据的类。这种技术不仅在多个运行的JVM之间共享只读数据,而且改善了启动速度,因为核心的JVM类是预包装的。

  性能人机工程学是J2SE 1.5的新特性。这意味着如果你在原先的版本中使用了特定的JVN运行期间选项,可能不必重新验证你的性能。

  监控和可管理性

  监控和可管理性是 Java 平台中的 RAS (Reliability, Availability, Serviceability,即可靠性、可用性、可服务性) 的一个关键组件。

  JVM监控和管理API指定了一套广泛的JVM内部实现方法,允许监视一个运行中的JVM。信息可以通过JMX ( JSR - 003) MBeans访问,并且可以在Java地址空间内本地访问或者使用JMX远程接口(JSR -160)和行业标准的SNMP协议工具来访问。

  最有用的一个特性就是低内存探测器。但超过阀值时,JMX MBeans可以通知注册的监听器什么时候达到临界值。

  J2SE 1.5提供了一个简单的方法,可以启动JVM和应用程序的out - of - the - box远程管理。例如,为了启动一个可被相同的本地计算机中的jconsole监视的应用程序,可以使用下面的系统属性:

Java -Dcom.sun.management.jmxremote -jar Java2Demo.jar

  并且,为了通过JMX监视它,而不需要验证,可以:

java -Dcom.sun.management.jmxremote.port=5001 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -jar Java2Demo.jar

  想了解如何简单地使用新的应用编程接口,下面记录了在HotSpot JVM中的内存堆栈的使用方法。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>import java.lang.management.*;
import java.util.*;
public class MemTest
{
 public static void main(String args[])
 {
  List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
  for (MemoryPoolMXBean p: pools)
  {
   System.out.println("Memory type="+p.getType()+" Memory usage="+p.getUsage());
  }
 }
}</td> </tr> </table>
  新的JVM应用编程接口(JSR - 163)

  这个版本中还包含了一个更加强大的本地应用编程接口,名为JVMTI。这个应用编程接口通过JSR - 163确定。然而,JVMTI是用来涵盖整套的本地访问的处理工具,除了简介以外还有监视、调试和潜在的各种其它代码分析工具。

  这个实现包括用于字节码实现的机制,Java程序语言实现服务( JPLIS)。这可以使分析工具只在需要的地方添加补充的简介。这种方法的好处是它允许更具体的分析并且限制了运行的JVM上的简介工具的干扰。这个工具甚至可以可以在运行期间动态地生成,此外还可以在类装载期间,作为类文件进行预处理。

  下面的示例创建了一个工具钩子,它可以从磁盘加载类文件的一个已修改的版本。要运行该测试,可利用 java -javaagent:myBCI BCITest 启动 JRE。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>//File myBCI.java import
java.lang.instrument.Instrumentation;
public class myBCI
{
 private static Instrumentation instCopy;
 public static void premain(String options, Instrumentation inst)
 {
  instCopy = inst;
 }
 public static Instrumentation getInstrumentation()
 {
  return instCopy;
 }
}
//File BCITest.java import java.nio.*;

import java.io.*;
import java.nio.channels.*;
import java.lang.instrument.*;
public class BCITest
{
 public static void main (String[] args)
 {
  try
  {
   OriginalClass mc = new OriginalClass();
   mc.message(); FileChannel fc=new FileInputStream( new File("modified"+File.separator+"OriginalClass.class")).getChannel();
   ByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, (int)fc.size());
   byte[] classBuffer = new byte[buf.capacity()];
   buf.get(classBuffer, 0, classBuffer.length);
   myBCI.getInstrumentation().redefineClasses( new ClassDefinition[] {
    new ClassDefinition(mc.getClass(), classBuffer)});
   mc.message();
  }
  catch (Exception e){}
 }
}
//OriginalClass.java
//Compile in current directory
//Copy source to modified directory,change message and recompile

public class OriginalClass
{
 public void message()
 {
  System.out.println("OriginalClass");
 }
}</td> </tr> </table>
  如果没有可用的控制台窗口,那么生成的堆栈追踪就很困难。两个新的API——getStackTrace和Thread.getAllStackTraces——以程序的方式提供该信息。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>StackTraceElement e[]=Thread.currentThread().getStackTrace();
for (int i=0; i <e.length; i++)
{
 System.out.println(e[i]);
}
System.out.println("\n"+Thread.getAllStackTraces());</td> </tr> </table>
  HotSpot JVM包括一个致命错误处理程序,如果JVM出现故障,可以运行一个用户提供的脚本或者程序。调试工具还可以使用HotSpot JVM的可维护性代理连接器连接到一个挂起的JVM或者核心文件。

-XX:OnError="command" -XX:OnError="pmap %p" -XX:OnError="gdb %p"optional %p used as process id
桌面客户端

  Java桌面客户端保留了Java平台的一个关键组成部分,并且这一点成了 J2SE 1.5 中许多改进的焦点。

  Beta2版包含了许多前面提到的在启动期间和内存大小方面的改善,J2SE1.5不仅更快,而且Swing工具包又有了一个新的主题,名为Ocean。通过基于J2SE 1.4.2中的更新,在GTK外观和Windows XP外观上有更进一步的改善。

<table width="99%" align="center" border="0"> <tr> <td>
Windows XP </td> <td>
Linux/RedHat </td> </tr> </table>
  具有最新 OpenGL 驱动程序并且选择了图形卡的 Linux 和 Solaris 用户,可以使用下面的运行时属性从 Java2D 获得本机硬件加速:

java -Dsun.java2d.opengl=true -jar Java2D.jar

  Linux 版本也具有快速的 X11 Toolkit,叫做 XAWT,默认情况下是启用的。如果您需要与 motif 版本进行比较,可以使用下面的系统属性:

java -Dawt.toolkit=sun.awt.motif.MToolkit -jar Notepad.jar

  X11工具包还使用XDnD协议,所以你可以在Java和其它像StarOffice或者Mozilla这样的应用程序之间拖放简单的组件。

  其他特性

  支持核心XML

  J2SE 1.5引入了几个核心XML平台的修订版,包括使用Namespaces和XML 1.1,XML Schema,SAX 2.0.2,DOM第三层支持以及使用快速的XLSTC编译器。

  除了支持核心XML之外,未来版本的 Java Web Services Developer Pack 将交付最新的 Web 服务标准:JAX-RPC & SAAJ (WSDL/SOAP)、JAXB、XML Encryption and Digital Signature,以及用于注册的 JAXR。

  辅助字符支持

  32 位的辅助字符支持作为传输到 Unicode 4.0 支持的一部分,已经慎重地添加到该平台。辅助字符被编码一对特殊的 UTF16 值,以生成一个不同的字符或者码点(codepoint)。一个代理对(surrogate pair)是一个高 UTF16 值和后面的一个低 UTF16 值的组合。这些高值和低值来自一个特殊范围的 UTF16 值。

  一般来说,当使用 String 或者字符序列时,核心 API 库将透明地为您处理新的辅助字符。但是因为 Java "char" 仍然保留为 16 位,所以非常少的一些使用 char 作为参数的方法,现在有了足够的可以接受 int 值的方法,其中 int 值可以代表新的更大的值。特别是 Character 类,具有附加的方法来检索当前的字符和接下来的字符,以便检索辅助的码点值,如下所示:

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>String u="\uD840\uDC08";
System.out.println(u+"+ "+u.length());
System.out.println(Character.isHighSurrogate(u.charAt(0)));
System.out.println((int)u.charAt(1));
System.out.println((int)u.codePointAt(0));</td> </tr> </table>
  JDBC RowSet

  在新版本Java中实现了五个新的JDBC RowSet类。最有价值的是CachedRowSet和WebRowSet。RowSet对象,与ResultSet对象不同,操作的时候可以不一直连接在数据库或者其他数据源上。这样,就不需要为连接一个数据源而付出高昂的代价,它们比ResultSet对象更加轻量级。CachedRowSet包含一个从数据库取得的非存储数据行集合,如果需要的话,它可以及时地同步化。此外WebRowSet实现可以用XML格式读写RowSet。

  下面的代码片段将显示创建使用一个WebRowSet对象是多么容易。

<table bordercolor="#ffcc66" width="90%" align="center" bgcolor="#e6e4dd" border="1"> <tr> <td>Class.forName("org.postgresql.Driver");
WebRowSetImpl wrs = new WebRowSetImpl();
wrs.setCommand("SELECT COF_NAME,TOTAL FROM COFFEES");
wrs.setUsername("postgres"); wrs.setPassword("");
wrs.setUrl("jdbc:postgresql:test");
wrs.execute();
// executes command and populates webset all coffees
wrs.absolute(1);
// moves cursor to the first row of wrs
wrs.updateInt(2, 10);
// reset total field to 10
wrs.updateRow();
// finishes edits to this row
wrs.acceptChanges();
// writes new total to the data source
wrs.writeXml(System.out);
// also exports rowset in XML format
wrs.close();</td> </tr> </table>
  小结

  总之,Tiger是一个以开发者为中心的版本。自Java语言诞生后,Java的发展速度就像是一个起飞的火箭一样,原因就在于它触动了开发者的心灵,点燃了他们的热情。这个版本的开发依然是基于这个思想。

  我们很幸运能有机会最早接触这些语言的新特性,使用它们是一种乐趣。在现有的各种开发语言中,Java本来就是一个非常好用而且富有生产力的语言,而所有的即将到来的新特性又会大大地增强使用它的乐趣。




↑返回目录
前一篇: J2SE:Java对各种文件的操作详解
后一篇: J2SE 6 的新特性,针对性能测试内存泄露而是个不错的东东