top
Loading...
“老虎”來了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。

下面的例子用元數據工具創建了一個調試元數據注釋,然后這些元數據注釋在運行時顯示出來。可以想像,大部分的元數據標簽形成一個標準,即一個良好規范的集合。

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);
}
}
}

使用元數據處理工具,許多重復的代碼步驟可以被簡化為一個簡明的元數據標簽。例如,當訪問一個JAX-RPC服務實現的時候,所需得遠程接口可以如下面的代碼這樣實現:

J2SE1.5版以前

public interface PingIF extends Remote
{
public void ping() throws RemoteException;
}
public class Ping implements PingIF
{
public void ping() { }
}

J2SE1.5

public class Ping
{
public @remote void ping() { }
}

泛型

泛型已經為Java社團所廣泛期待,現在成了J2SE 1.5版的一個組成部分。最先能看到泛型起作用的地方就是Collection API。Collection API提供了像LinkedLists, ArrayLists 和 HashMaps這樣的函數,可以被不止一種的Java類型使用。接下來的示例中使用了1.4.2庫和默認的javac編譯方式。

ArrayList list = new ArrayList();
list.add(0, new Integer(42));
int total = ((Integer)list.get(0)).intValue();

最后一行中的 Integer 轉換是泛型所要防止的強制類型轉換問題的一個例子。問題是1.4.2版本中,Collection API使用Object類來保存Collection對象,這意味著在編譯時不能找出任何類型匹配。問題的第一個標志信息是在運行時拋出的 ClassCastException。

使用泛型化的Collection庫編寫的相同示例如下:

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = list.get(0).intValue();

使用泛型應用編程接口的用戶必須只使用<>符號聲明在編譯類型中使用的類型,不需要進行任何類型強制轉換,在本例中試圖向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版前

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, new Integer(42));
int total = (list.get(0)).intValue();

1.5版

ArrayList<Integer> list = new ArrayList<Integer>();
list.add(0, 42);
int total = list.get(0);

增強的 for循環

Collections API經常使用Iterator類。 Iterator類提供在 Collection 中遍歷導航的機制。當在集合和數組中遍歷時,新的增強的 for 循環可取代 iterator。編譯器生成必要的循環代碼,因為利用范型,所以不需要額外的類型轉換。

以前

ArrayList<Integer> list = new ArrayList<Integer>();
for (Iterator i = list.iterator(); i.hasNext();)
{
Integer value=(Integer)i.next();
}

現在

ArrayList<Integer> list = new ArrayList<Integer>();
for (Integer i : list)
{
...
}

枚舉類型

當使用 static final 型常量時,該類型提供枚舉的類型。如果你以前在你自己的應用程序中使用過enum標識符,那么在利用J2SE1.5進行編譯時需要修改源代碼。

public enum StopLight
{
red, amber, green
};

靜態導入

靜態導入特性實現了"import static",允許您從一個類引用靜態常量,而不需要繼承它。例如,我們添加一個組件的時候不需要每次都使用BorderLayout.CENTER,而是只引用CENTER就可以了。

import static java.awt.BorderLayout.*;
getContentPane().add(new JPanel(), CENTER);

格式化輸出

開發者現在可以選擇使用printf類型的函數來生成格式化輸出。這樣有助于將C語言應用程序中移植到Java上,這樣文本布局可以基本沒有什么變化。

大部分公用的C語言的printf的格式標識符都可以用,此外一些Java類像Date和BigInteger也有了格式化規則。

System.out.printf("name count%n");
System.out.printf("%s %5d%n", user,total);

格式化輸入

scanner應用編程接口提供了用于從系統控制臺或者任何數據流讀出數據的基本輸入功能。下面的示例從標準輸入讀取一個字符串。

如果沒有數據可用的話,像next和nextInt這樣的方法將阻塞。如果你需要處理更加復雜的輸入,那么還有模式匹配算法,可以從java.util.Formatter類中獲得。

Scanner s= new Scanner(System.in);
String param= s.next();
int value=s.nextInt();
s.close();

可變參數

可變參數功能允許多個參數作為傳入方法的參數。它只需要簡單的"..."表示法,該符號用于接收參數列表的方法,并且它還被用于實現 printf 所需參數的靈活數量。

void argtest(Object ... args)
{
for (int i=0;i <args.length; i++) { }
}
argtest("test", "data");

并行性實用程序

并行實用程序庫由Doug Lea定義在 JSR-166 中,是一個J2SE 1.5平臺中公用的并發程序包的特殊版本。它提供了強大的,高級的線程構成器,包括executors(這是一個線程任務框架)、線程安全隊列、Timers、鎖(包括原子鎖)和其他同步原語。

著名的旗語(semaphore)是這樣一個鎖。semaphore和現在使用的wait的使用方式相同,用于限制對代碼塊的訪問。Semaphore更加靈活,可以允許許多并發的線程訪問,還允許在獲得一個鎖定之前測試它。下面的示例只使用了一個semaphore,也稱二元semaphore。

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
}
}

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中的內存堆棧的使用方法。

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());
}
}
}

新的JVM應用編程接口(JSR - 163)

這個版本中還包含了一個更加強大的本地應用編程接口,名為JVMTI。這個應用編程接口通過JSR - 163確定。然而,JVMTI是用來涵蓋整套的本地訪問的處理工具,除了簡介以外還有監視、調試和潛在的各種其它代碼分析工具。

這個實現包括用于字節碼實現的機制,Java程序語言實現服務( JPLIS)。這可以使分析工具只在需要的地方添加補充的簡介。這種方法的好處是它允許更具體的分析并且限制了運行的JVM上的簡介工具的干擾。這個工具甚至可以可以在運行期間動態地生成,此外還可以在類裝載期間,作為類文件進行預處理。

下面的示例創建了一個工具鉤子,它可以從磁盤加載類文件的一個已修改的版本。要運行該測試,可利用 java -javaagent:myBCI BCITest 啟動 JRE。

//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");
}
}

如果沒有可用的控制臺窗口,那么生成的堆棧追蹤就很困難。兩個新的API——getStackTrace和Thread.getAllStackTraces——以程序的方式提供該信息。

StackTraceElement e[]=Thread.currentThread().getStackTrace();
for (int i=0; i <e.length; i++)
{
System.out.println(e[i]);
}
System.out.println(""+Thread.getAllStackTraces());

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外觀上有更進一步的改善。


Windows XP

Linux/RedHat

具有最新 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 類,具有附加的方法來檢索當前的字符和接下來的字符,以便檢索輔助的碼點值,如下所示:

String u="uD840uDC08";
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));

JDBC RowSet

在新版本Java中實現了五個新的JDBC RowSet類。最有價值的是CachedRowSet和WebRowSet。RowSet對象,與ResultSet對象不同,操作的時候可以不一直連接在數據庫或者其他數據源上。這樣,就不需要為連接一個數據源而付出高昂的代價,它們比ResultSet對象更加輕量級。CachedRowSet包含一個從數據庫取得的非存儲數據行集合,如果需要的話,它可以及時地同步化。此外WebRowSet實現可以用XML格式讀寫RowSet。

下面的代碼片段將顯示創建使用一個WebRowSet對象是多么容易。

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();

小結

總之,Tiger是一個以開發者為中心的版本。自Java語言誕生后,Java的發展速度就像是一個起飛的火箭一樣,原因就在于它觸動了開發者的心靈,點燃了他們的熱情。這個版本的開發依然是基于這個思想。

我們很幸運能有機會最早接觸這些語言的新特性,使用它們是一種樂趣。在現有的各種開發語言中,Java本來就是一個非常好用而且富有生產力的語言,而所有的即將到來的新特性又會大大地增強使用它的樂趣。
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗