<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 97,  comments - 93,  trackbacks - 0
    Java SE 6.0(代號Mustang,野馬)已經(jīng)發(fā)布,詳情請見 野馬奔騰而出,Java SE 6 正式版發(fā)布 ,它給我們帶來了哪些新的特性了。

        首先,我們看看JDK 6.0包含了大量的JSR,分為四組,分別為:

        在簡化開發(fā)方面:

    199: Compiler API
    269: Annotation Processors
    260: Javadoc™ Tag Update Ease of Development
    221: JDBC™ 4.0
    223: Scripting for the Java Platform

    在XML方面:
    105: XML Digital Signature(數(shù)字簽名)
    173: Streaming API for XML XML
    222: JAXB 2.0

    在Web 服務(wù)方面
    250: Common Annotations
    181: WS Metadata Web Services
    224: JAX-WS 2.0

    其它:

    202: Java Class 文件規(guī)范升級

        詳情參見JSR 270,其鏈接為 http://jcp.org

        除了制定相應(yīng)的一系列的JSR之外,野馬所有的新特性是圍繞下面的目標(biāo)展開的:

    • 兼容性和穩(wěn)定性(Compatibility and stability)
    • 可診斷性,監(jiān)控和管理(Diagnosability, monitoring, and management)
    • 減輕開發(fā)量(Ease of development)
    • 企業(yè)級桌面(Enterprise desktop)
    • XML和Web 服務(wù)(XML and web services)
    • 透明性(Transparency)

    要實(shí)現(xiàn)這些目標(biāo),必然要增加不少代碼。其結(jié)果是JDK的個頭比原來的大了不少,安裝后JDK 6.0的大小為(169,346,858 字節(jié));而JDK 5.0 update 7的大小為(124,808,838 字節(jié))。

        從源代碼結(jié)構(gòu)上來看,增加了如下的新包:

    包名

    描述

    java.text.spi

    java.text包的服務(wù)提供者類

    java.util.spi

    java.util包的服務(wù)提供者類

    javax.activation

    激活框架

    javax.annotation

    標(biāo)注處理支持

    javax.jws

    Web 服務(wù)支持類

    javax.jws.soap

    SOAP 支持類

    javax.lang.model.*

    支持編程語言的建模和語言元素與類型的處理

    javax.script

    Java 腳本語言引擎支持框架

    javax.tools

    提供類工具的訪問,譬如編譯器

    javax.xml.bind.*

    與 JAXB 相關(guān)的支持

    javax.xml.crypto.*

    與XML 密碼系統(tǒng)相關(guān)的支持

    javax.xml.soap

    支持建立和構(gòu)建SOAP 消息

    javax.xml.stream.*

    支持XML

    Streaming API

    javax.xml.ws.*

    支持JAX-WS

            在今年九月份的Sun Tech Day China上,Sun 的一個講師說,有十個可能忽視的有趣的東東,現(xiàn)列表如下:

    10. 按需即附監(jiān)視;

    9. JConsole 插件 API;

    8. jhat OQL (jmap heap dump);

    7. Solaris 動態(tài)跟蹤(DTrace)支持(在Solaris OS下);

    6. 由 javac 完成標(biāo)注處理;

    5. 類路徑(Class-path)*匹配;

    4. 磁盤剩余空間 API;

    3. 密碼提示;

    2. Swing 新增布局管理器javax.swing.GroupLayout;

    1. JDK 內(nèi)置一個服器,JAX-WS 完成web 服務(wù)。

    此為Java SE 6.0的新特性的開篇,今后將陸續(xù)就新特性進(jìn)行詳細(xì)說明。


    一、存取權(quán)限控制方法

    從某種角度看,F(xiàn)ile類的一個實(shí)例其實(shí)是一個標(biāo)識文件系統(tǒng)中文件或目錄對象的抽象路徑名。文件系統(tǒng)可以限制在這個對象上實(shí)現(xiàn)的讀、寫以及執(zhí)行等操作。

    讀、寫和執(zhí)行限制統(tǒng)稱為“存取權(quán)限”。文件系統(tǒng)可以把多個存取權(quán)限集合關(guān)聯(lián)到單個對象。例如,一個集合可以用于對象的所有者而另一個集合可以用于所有的其他用戶。

    前一個版本中提供的存取權(quán)限在直接用于存取對象時,有可能會導(dǎo)致File類的一些方法失敗。由于這個原因,Mustang為File類引入了六種新的方法以便讓你修改路徑名的存取權(quán)限:

    ①“public boolean setExecutable(boolean executable, boolean ownerOnly)”:設(shè)置所有者或每個人對于指定抽象路徑名的執(zhí)行許可權(quán)。當(dāng)executable為true時,允許執(zhí)行操作;而傳遞給它的值為 false時,則不允許執(zhí)行。把true傳遞給參數(shù)ownerOnly僅允許該抽象路徑名的所有者擁有該許可權(quán);當(dāng)ownerOnly為false,則把 該許可權(quán)授予每個人。如果底層文件系統(tǒng)無法區(qū)分所有者的執(zhí)行許可與每個人的執(zhí)行許可,那么,該許可應(yīng)用于每個人,而不管ownerOnly取值如何。

    該方法在成功時返回true;否則,返回false。如果用戶無權(quán)改變抽象路徑名的存取權(quán)限或如果底層文件系統(tǒng)沒有實(shí)現(xiàn)一種執(zhí)行許可并且executable為false,則方法調(diào)用失敗。

    ②“public boolean setExecutable(boolean executable)”:這個方法便于設(shè)置所有者對于給定抽象路徑名的執(zhí)行權(quán)限。

    ③public oolean setReadable( oolean readable, oolean ownerOnly)”:設(shè)置所有者或每個人對于這個抽象路徑名的讀取許可權(quán)。參數(shù)readable為true時允許讀取操作;否則,不允許讀取。參數(shù) ownerOnly為true時僅允許該抽象路徑名的所有者擁有該許可權(quán);當(dāng)ownerOnly為false,則把該許可權(quán)授予每個人。如果底層文件系統(tǒng) 無法區(qū)分所有者的讀取許可與每個人的讀取許可,那么,該許可應(yīng)用于每個人,而不管ownerOnly取值如何。

    該方法在成功時返回true;否則,返回false。如果用戶無權(quán)改變抽象路徑名的存取權(quán)限或如果底層文件系統(tǒng)沒有實(shí)現(xiàn)一種讀取許可并且readable為false,則方法調(diào)用會失敗。

    ④“public boolean setReadable(boolean readable)”:這個方法便于設(shè)置所有者對于給定抽象路徑名的讀取權(quán)限。

    ⑤“public boolean setWritable(boolean writable,boolean ownerOnly)”:設(shè)置所有者或每個人對于這個抽象路徑名的寫許可權(quán)。參數(shù)writable為true時允許寫操作;否則,不允許寫操作。參數(shù) ownerOnly為true時僅允許該抽象路徑名的所有者擁有該許可權(quán);當(dāng)ownerOnly為false,則把該許可權(quán)授予每個人。如果底層文件系統(tǒng) 無法區(qū)分所有者的寫許可與每個人的寫許可,那么,該許可應(yīng)用于每個人,而不管ownerOnly取值如何。

    該方法在成功時這個方法返回true;否則,返回false。如果用戶無權(quán)改變抽象路徑名的存取權(quán)限,則方法調(diào)用會失敗。

    ⑥“public boolean setWritable(boolean writable)”:這個方法便于設(shè)置所有者對于給定抽象路徑名的寫權(quán)限。

    【注意】如果存在一個安全管理器并且它的“public void checkWrite(String file)”方法不允許對文件進(jìn)行寫操作的話,則上面列出的每一個方法都會拋出一個SecurityException異常。

    File類還提供了如下對應(yīng)的方法以幫助你獲得一個對象當(dāng)前設(shè)置的讀、寫和執(zhí)行權(quán)限:

    ①public boolean canRead();

    ②public boolean canWrite();

    ③public boolean canExecute()(在Mustang中新引入的)。
    二、桌面集成

       Sun的Java桌面開發(fā)小組引入了若干新的特征以進(jìn)一步提高Java在桌面開發(fā)領(lǐng)域的影響。其中三個著名的特征是:Splash屏幕支持(它讓應(yīng)用 程序在啟動過程中顯示Splash屏幕),系統(tǒng)托盤支持(它讓應(yīng)用程序把圖標(biāo),提示窗信息和彈出菜單添加到系統(tǒng)托盤),和一組新的桌面API。

    現(xiàn)在,我們來討論桌面API,它有助于無縫地把Java應(yīng)用程序與桌面集成到一起。該API支持Java應(yīng)用程序使用一個特定的統(tǒng)一資源標(biāo)識符 (URI)啟動操作系統(tǒng)的缺省的瀏覽器;啟動OS的缺省的電子郵件客戶端;以及啟動應(yīng)用程序以打開、編輯或打印與該應(yīng)用程序相關(guān)聯(lián)的文件。

    桌面API使用OS的文件關(guān)聯(lián)機(jī)制來啟動關(guān)聯(lián)到特定的文件類型的應(yīng)用程序。例如,.doc文件擴(kuò)展經(jīng)常與微軟的Word關(guān)聯(lián)。經(jīng)由桌面API,一個Java應(yīng)用程序能夠啟動Word以打開、打印或編輯與這個擴(kuò)展名相關(guān)聯(lián)的文件。

    在啟動瀏覽器電子郵件客戶端或任何應(yīng)用程序之前,你的Java應(yīng)用程序必須決定你的OS是否支持該API。這一決定是通過調(diào)用 java.awt.Desktop類的“public static boolean isDesktopSupported()”方法實(shí)現(xiàn)的。如果OS支持該API,這個方法返回true;否則,它返回false。

    在調(diào)用isDesktopSupported()之后,該應(yīng)用程序通過調(diào)用Desktop的“public static Desktop getDesktop()”方法繼續(xù)檢索Desktop對象。如果OS不支持鍵盤輸入、顯示器或鼠標(biāo),這個方法將拋出一個 java.awt.Headless異常。如果OS不支持該桌面API,則拋出一個UnsupportedOperationException異常。

    現(xiàn)在,既然該Java應(yīng)用程序已經(jīng)擁有了一個桌面實(shí)例,那么,按下來,它就能夠調(diào)用各種方法以瀏覽、發(fā)送郵件、打開、編輯或打印。在執(zhí)行任何這些操作 之前,該程序可以調(diào)用Desktop的“public boolean isSupported(Desktop.Action action)”方法,如果桌面支持該行為(被描述為適合的Desktop.Action枚舉實(shí)例),則這個方法返回true。這些 Desktop.Action枚舉如下:

    · BROWSE:這個枚舉實(shí)例描述OS的缺省瀏覽器的瀏覽行為。

    · MAIL:這個枚舉實(shí)例描述OS的缺省電子郵件客戶端的郵件行為。

    · OPEN:這個枚舉實(shí)例描述與打開一個特定的文件類型相關(guān)聯(lián)的一個應(yīng)用程序執(zhí)行的打開行為。

    · EDIT:這個枚舉實(shí)例描述與編輯一個特定的文件類型相關(guān)聯(lián)的一個應(yīng)用程序執(zhí)行的編輯行為。

    · PRINT:這個枚舉實(shí)例描述與打印一個特定的文件類型相關(guān)聯(lián)的一個應(yīng)用程序執(zhí)行的打印行為。

    【注意】在調(diào)用相應(yīng)行為的Desktop方法前,你不必調(diào)用“isSupported(Desktop.Action action)”來決定是否支持該行為:你可以直接調(diào)用相應(yīng)的方法,但是之后,你必須處理該方法潛在地拋出的一個 UnsupportedOperationException異常。可以從Desktop存取下列行為方法:

    ①“public void browse(URI uri)”:啟動用戶缺省的瀏覽器以顯示一個URI—如果瀏覽器能夠處理這個URI的話;否則,它啟動該URI缺省的處理器應(yīng)用程序(這具體要依賴于在java.net.URI類中定義的協(xié)議和路徑)。

    如果uri為null,則拋出一個NullPointerException異常。如果用戶的缺省瀏覽器沒有找到或它沒能啟動或缺省的處理器應(yīng)用程序沒能啟動,則拋出一個java.io.IOException異常。
    ②“public void edit(File file)”:啟動相關(guān)聯(lián)的編輯器應(yīng)用程序并且打開一個文件進(jìn)行編輯。
    如果file為null,則拋出一個NullPointerException異常。如果指定的文件不存在,則拋出一個 IllegalArgumentException異常。最后,如果指定的文件相關(guān)聯(lián)的應(yīng)用程序沒能啟動,或這個文件沒有相關(guān)聯(lián)的編輯器,則拋出一個 IOException異常。

    ③“public void mail()”:啟動用戶缺省的電子郵件客戶端的郵件編輯窗口。

    如果用戶缺省的電子郵件客戶端沒有發(fā)現(xiàn)或啟動失敗,則拋出一個IOException異常。

    ④“public void mail(URI mailtoURI)”:啟動用戶缺省的電子郵件客戶端的郵件編輯窗口,填充由一個“mailto:”URI指定的消息域。這個URI能夠指定包括“cc”,“subject”和“body”在內(nèi)的各種消息域。

    如果mailtoURI為null,則拋出一個NullPointerException異常。如果URI的模式不是mailto,則拋出一個 IllegalArgumentException異常。如果用戶缺省的電子郵件客戶端沒有發(fā)現(xiàn)或啟動失敗,則拋出一個IOException異常。

    ⑤“public void open(File file)”:啟動相關(guān)聯(lián)的應(yīng)用程序以打開該文件。如果指定的文件是一個目錄,則啟動OS的文件管理器以打開它。

    如果file為 null,則拋出一個NullPointerException異常。如果指定的文件不存在,則拋出一個 IllegalArgumentException異常。最后,如果該指定的文件沒有相關(guān)聯(lián)的應(yīng)用程序,或如果這個應(yīng)用程序沒能啟動,則拋出一個 IOException異常。

    ⑥“public void print(File file)”:使用相關(guān)聯(lián)的應(yīng)用程序的打印命令并使用本地桌面打印設(shè)備打印一個文件。

    如果file為null,則拋出一個NullPointerException異常。如果指定的文件不存在,則拋出一個 IllegalArgumentException異常。如果指定的文件沒有相關(guān)聯(lián)的能夠用于打印其內(nèi)容的應(yīng)用程序,則拋出一個IOException異 常。

    【注意】如果一個安全管理器存在并且不允許執(zhí)行要求的行為的話,上面列出的每一個方法都會拋出一個SecurityException異常。
    三、以編程方式存取網(wǎng)絡(luò)參數(shù)

    Mustang提供了以編程方式存取網(wǎng)絡(luò)參數(shù)的方法—這是通過在java.net.NetworkInterface類和新的java.net.InterfaceAddress類中提供的10個新的方法實(shí)現(xiàn)的。這些新引入的網(wǎng)絡(luò)接口方法列舉如下:

    ①“public byte[] getHardwareAddress()”:以一個字節(jié)數(shù)組形式返回這個網(wǎng)絡(luò)接口的硬件地址(通常是機(jī)器地址代碼,或MAC—也稱作以太網(wǎng)地址)。如果 這個接口沒有一個硬件地址,或如果不能存取這個地址(因?yàn)樵撚脩魶]有足夠的權(quán)限),則返回null。如果發(fā)生一個I/O錯誤,則拋出一個 java.net.SocketException異常。

    ②“public List<InterfaceAddress> getInterfaceAddresses()”:返回一個java.util.List,它包含這個網(wǎng)絡(luò)接口的所有接口地址(作為 InterfaceAddress實(shí)例)或其中一個子集。如果存在一個安全管理器,那么將使用相應(yīng)于每一個接口地址的 java.net.InetAddress來調(diào)用它的一個checkConnect方法。注意,這個方法僅在列表中返回 InterfaceAddresses;而且此時,checkConnect并不拋出一個SecurityException異常。

    ③“public int getMTU()”:返回這個網(wǎng)絡(luò)接口的最大傳輸單位(MTU)。該MTU指的是一個通訊協(xié)議層能夠傳遞到另一個層的最大包的大小(以字節(jié)為單位)。例 如,以太網(wǎng)允許的最大MTU是1500字節(jié)。根據(jù)某一標(biāo)準(zhǔn)(例如以太網(wǎng))或連接時間(在端到端串行連接時,經(jīng)常有這種情況),該MTU能夠被設(shè)置為一個固 定長度。如果發(fā)生一個I/O錯誤,則拋出一個SocketException異常。

    ④“public NetworkInterface getParent()”:如果這個網(wǎng)絡(luò)接口是一個子接口,則返回這個網(wǎng)絡(luò)接口的父網(wǎng)絡(luò)接口(作為一個NetworkInterface實(shí)例)。然而,如 果這個網(wǎng)絡(luò)接口是一個物理(非虛擬的)接口或如果這個網(wǎng)絡(luò)接口是虛擬的并且沒有父接口,則返回null。

    ⑤“public Enumeration<NetworkInterface> getSubInterfaces()”:返回一個包含所有的子接口(也稱為虛擬接口)的java.util.Enumeration(作為 NetworkInterface的實(shí)例)。例如,eth0:1是一個eth0的子接口(一個以太網(wǎng)網(wǎng)絡(luò)接口名)。

    ⑥“public boolean isLoopback()”:返回true,如果這個網(wǎng)絡(luò)接口是一個loopback接口(一種網(wǎng)絡(luò)接口,在該接口中,外發(fā)數(shù)據(jù)作為輸入數(shù)據(jù)被立即反射回 該接口)。如果存在一個I/O問題,則拋出一個SocketException異常。

    ⑦“public boolean isPointToPoint()”:返回true,如果這個網(wǎng)絡(luò)接口是一個端到端的接口(例如一個通過調(diào)制解調(diào)器建立的PPP連接)。如果存在一個I/O問題,則拋出一個SocketException異常。

    ⑧“public boolean isUp()”:返回true,如果這個網(wǎng)絡(luò)接口是“up”并且已經(jīng)“running”。“up”指示已經(jīng)為這個接口建立起了路由入口。 “running”指示要求的系統(tǒng)資源已經(jīng)分配。如果存在一個I/O問題,則拋出一個SocketException異常。

    ⑨“public boolean isVirtual()”:返回true,如果這個網(wǎng)絡(luò)接口是一個虛擬接口(也稱作“子接口”)。如果存在一個I/O問題,則拋出一個SocketException異常。

    ⑩“public boolean supportsMulticast()”:返回true,如果這個網(wǎng)絡(luò)接口支持多點(diǎn)傳送(指一個服務(wù)器程序把一個消息的一個副本發(fā)送給多個客戶端程序的 能力)。如果存在一個I/O問題,則拋出一個SocketException異常。

    InterfaceAddress類描述了一個網(wǎng)絡(luò)接口地址。除了通常的實(shí)現(xiàn)獲得一個哈希代碼和獲得一個字符串描述等方法之外,這個類還提供了下列三個方法:

    · “public InetAddress getAddress()”:返回給定接口地址:一個IP地址,一個子網(wǎng)掩碼和一個廣播地址(當(dāng)該地址是IPv4時);或是一個IP地址和一個網(wǎng)絡(luò)前綴長度(針對一個IPv6地址)。

    · “public InetAddress getBroadcast()”:返回給定接口地址的廣播地址(在IPv4網(wǎng)絡(luò)中作為一個InetAddress);在IPv6網(wǎng)絡(luò)中則返回null(此時它沒有廣播地址)。

    · “public short getNetworkPrefixLength()”:返回給定接口地址的針對IPv6網(wǎng)絡(luò)的網(wǎng)絡(luò)前綴長度(或針對IPv4網(wǎng)絡(luò)的子網(wǎng)掩碼)。這個方法的返回值為一個短整型。

    【注意】 典型的IPv6值是128(::1/128)或10(fe80::203:baff:fe27:1243/10)。針對IPv4的典型的值是8(255.0.0.0),16(255.255.0.0),或24(255.255.255.0)。

    Java Web 涉及到的JSR有 105,173,181,222,224,250。

    由于Web服務(wù)日趨流行,利用 Web服務(wù)的功能性的API特征正從最新的Java EE版本中向Java SE 6平臺遷移。換言之,針對Web服務(wù)不需另外加入額外的工具,在Java EE和Java SE平臺擁有相同的API。野馬將大把不同的Web服務(wù)相關(guān)的API加到標(biāo)準(zhǔn)的工具柜中:以JSR 181針對Java 平臺的Web服務(wù)元數(shù)據(jù),通過JSR 224的基于XML 的Web服務(wù)Java API(JAX-WS);針對Java的帶有附件的SOAP API(SAAJ)作為JSR 67

    與三個Web服務(wù)API相關(guān)的包新增到Java SE 6.0里JAX-WS API 放置到javax.xml.ws包; SAAJ類在javax.xml.soap 包; Web服務(wù)的元數(shù)據(jù)類放置在javax.jws包里。

    javax.jws

    JSR 181 及其針對Java 平臺Web服務(wù)元數(shù)據(jù)的規(guī)范提供一個在類中利用標(biāo)注設(shè)計和開發(fā)Web服務(wù)的機(jī)制。標(biāo)注從J2SE 5.0引入,在Java SE 6.0得到了進(jìn)一步擴(kuò)展。在第10章將會完整描述。但是,標(biāo)注基本上允許將@tag加入到類,方法和特性來描述相關(guān)的元數(shù)據(jù)。一個解析器然后能定位標(biāo)記并 采取適當(dāng)?shù)男袆樱槐M管行動什么時候發(fā)生完全依賴于標(biāo)記自身。

    JAX-WS 2.0 很容易使用. 本文將介紹如何使用Java SE 6。以JAX-WS如何建立一個簡單的Web服務(wù)。首先建立一個建立一個將要作為Web服務(wù)發(fā)布的類,如表1所示:

    Java 代碼 列表1

    package  hello;

    public   class  CircleFunctions  {

       
    public   double  getArea( double  radius)  {
           
    return  java.lang.Math.PI  *  (r  *  r);
        }


       
    public   double  getCircumference( double  radius)  {
           
    return   2   *  java.lang.Math.PI  *  r;
       }

    }


    為了輸出這些方法,必需做兩件事情:引入javax.jws.WebService  包;在類的前面增加@WebService  標(biāo)注以告訴Java編譯器將發(fā)布此類為Web服務(wù)。下面的代碼顯示了這種變化(以黑體顯示增加的代碼)。

    Java 代碼 列表2
    package hello;

    import javax.jws.WebService;

    @WebService

    public class CircleFunctions {
       
    public double getArea(double r) {
           
    return java.lang.Math.PI * (r * r);
        }


       
    public double getCircumference(double r) {
            
    return 2 * java.lang.Math.PI * r;
        }


    }



    在此,有兩個基本的標(biāo)注@WebService@WebMethod。@WebService標(biāo)注指明HelloService 類作為Web服務(wù)。如果沒有制定,標(biāo)注的名稱就是類的名稱。也能制定命名空間,服務(wù)名,WSDL 位置和endpoint 接口等。在指定的上下文環(huán)境中,可以使用javax.xml.ws.Endpoint類的publish()靜態(tài)方法發(fā)布上面的類作為Web服務(wù)。代碼見列表3:

    Java 代碼 列表3

    import javax.xml.ws.Endpoint;

    public static void main(String[] args) {

          Endpoint.publish(
             
    "http://localhost:8080/WebServiceExample/circlefunctions",
             
    new CircleFunctions());
            
    try {
                System.in.read();
            }
     catch (IOException ex) {
                ex.printStackTrace();
            }

    }



    現(xiàn)在,用javac編譯源代碼。但是源文件能做什么呢?通過對源文件運(yùn)行 javac編譯器進(jìn)行編譯只是產(chǎn)生了class文件。并沒有產(chǎn)生特殊的東西。但是在編譯類之后,也需要運(yùn)行wsgen 命令行工具(wsgen 是Web service generator的縮寫)。編譯源代碼后還必需完成更多的步驟:像下面一樣調(diào)用wsgen工具。

    > wsgen –cp . hello.CircleFunctions
    Wsgen工具將在一個叫做wsgen子目錄下產(chǎn)生大量的源代碼,然后將這些源代碼編譯成class文件。盡管從未編輯這些文件,但是可以瀏覽這些文件。注意在使用Wsgen工具時,原始的源代碼必需在相應(yīng)的包里。否則將產(chǎn)生錯誤。

    就這么簡單。當(dāng)運(yùn)行應(yīng)用程序時,Java SE 6平臺擁有一個小的Web應(yīng)用服務(wù)器,它將在地址為http://localhost:8080/WebServiceExample/circlefunctions 發(fā)布Web服務(wù)。通過顯示CircleFunction的WSDL 來驗(yàn)證Web服務(wù)。當(dāng)JVM仍然運(yùn)行時,在瀏覽器輸入:


    如果在瀏覽器里看見大量描述Web服務(wù)的功能的XML代碼,那么Web服務(wù)就成功發(fā)布了。

    四、 表格排序與過濾

    Swing的表格組件在若干方面得到了增強(qiáng)。其中的一個改進(jìn)是,支持對一個表格中的行數(shù)據(jù)進(jìn)行按升/降序排序并且能夠過濾掉其中某些行(所有數(shù)據(jù)來自于表格模型),并最終顯示在組件的視圖中。

    【請記住】排序和過濾僅對視圖有影響,而對模型無影響。


    排序和過濾基于一個新概念—行排序器對象,它能夠?qū)π袛?shù)據(jù)進(jìn)行排序(和過濾)。把一個行排序器加入到一個表格組件中的最簡單的方法是調(diào)用 javax.swing.JTable中新引入的“public void setAutoCreateRowSorter(boolean autoCreateRowSorter)”方法,下面的代碼片斷演示了它的用法:

    TableModel model = createTableModel ();

    JTable table = new JTable (model);
    table.setAutoCreateRowSorter (true);

    在每次改變模型時,把true傳遞給setAutoCreateRowSorter()能夠使JTable安裝一個新的 javax.swing.Table.TableRowSorter<M>實(shí)例作為行排序器。為了防止在以后改變模型時再創(chuàng)建新的行排序器, 可以把false傳給一個隨后調(diào)用的方法。

    注意,當(dāng)你不想定制行排序器時,你也有可能調(diào)用setAutoCreateRowSorter()。但是,在調(diào)用這個方法后,你仍然能夠定制行排序 器,這是通過首先調(diào)用JTable的新的“public RowSorter<? extends TableModel> getRowSorter()”方法以返回當(dāng)前行排序器來實(shí)現(xiàn)的。


    因?yàn)楫?dāng)你試圖把返回的行排序器的引用存儲到一個TableRowSorter時編譯器會顯示一個未檢查的警告消息,所以,你可能更喜歡由你自己創(chuàng)建表 格行排序器并使用JTable的新的“public void setRowSorter(RowSorter<? extends TableModel> sorter)”方法來安裝它:

    TableRowSorter<TableModel> sorter;

    sorter = new TableRowSorter<TableModel> (model);
    table.setRowSorter (sorter);

    對TableRowSorter的定制還包括能夠使用它的“public void setRowFilter(RowFilter<? super M,? super I> filter)”方法安裝一個行過濾對象(它基于某個標(biāo)準(zhǔn)接收行數(shù)據(jù))。這個方法接收一個javax.swing.RowFilter<M, I>參數(shù),其相應(yīng)的方法能夠返回不同種類的行過濾器。

    有些行過濾器可以使用正規(guī)表達(dá)式。為了獲得這種行過濾器,可以調(diào)用“RowFilter public static <M,I> RowFilter<M,I> regexFilter(String regex, int... indices)”方法。例如,“sorter.setRowFilter (RowFilter.regexFilter ("^A"));”語句能夠創(chuàng)建一個行過濾器,它的“^A”正規(guī)表達(dá)式僅接受以A開始的行。


    JTable還提供了其它一些與排序和行過濾有關(guān)的新方法。這其中的兩個是:“public int convertRowIndexToModel(int viewRowIndex)”和“public int convertRowIndexToView(int modelRowIndex)”,它們分別負(fù)責(zé)把一個行的索引(根據(jù)模型)映射到視圖和把一個行的索引(根據(jù)視圖)映射到模型。

    為了向你說明僅是視圖為排序和過濾所影響,我使用了前面的TableSortFilterDemo演示應(yīng)用程序中的一個“convert”方法。在改 變行過濾器以后,除了把null傳遞給TableRowSorter的“public void setSortKeys(List<? extends RowSorter.SortKey> sortKeys)”方法以打亂視圖的排序外,列表4(見本文示例源程序)中其它的內(nèi)容我們都已經(jīng)討論過。


    在編譯和運(yùn)行這個應(yīng)用程序后,通過點(diǎn)擊某一列的列頭部初始化一個排序。作為響應(yīng),所有的行按被點(diǎn)擊的列值重新升序或降序排列(每次點(diǎn)擊使之在升序與降序之間切換)。選擇的列和排序順序以相應(yīng)列頭部的一個向上/向下的箭頭指示

    除了排序之外,你還能夠安裝一個過濾器以決定在視圖中顯示哪些行。為此,只要在文本域中輸入一個正規(guī)表達(dá)式(例如^J或J),并且點(diǎn)擊“Set Filter”按鈕即可。作為響應(yīng),所有的匹配該正規(guī)表達(dá)式的行都被以非排序方式顯示。然后,你可以再對這些行進(jìn)行排序。
    Security:安全性
    Java SE 6的安全部分,增加了 XML-Digital Signature (XML-DSIG) APIs, 整合了GSS/Kerberos的操作API,LDAP上的JAAS認(rèn)證
    六、 Java SE 6中的Java DB
       雖然Java DB僅占用2兆字節(jié)(MB)空間,它卻是一個先進(jìn)的全事務(wù)處理的基于Java技術(shù)的數(shù)據(jù)庫,它支持各類開放標(biāo)準(zhǔn)、觸發(fā)器和存儲程序。Java DB可以客戶端服務(wù)器模式使用,也可以直接嵌入到一個Java應(yīng)用程序中。在這些場合,Java DB都可以在同樣的Java虛擬機(jī)(JVM)中運(yùn)行,這就無需在應(yīng)用程序之外單獨(dú)購買、下載、安裝或管理這個數(shù)據(jù)庫。對于選擇在生產(chǎn)中采用Java DB的客戶,Sun將提供支持服務(wù)。

      腳本語言與 Java(吳玥顥,目前就職于 IBM 中國開發(fā)中心 Harmony 開發(fā)團(tuán)隊(duì)。 除了對 Java 和腳本語言的熱愛之外,他的興趣還包括哲學(xué)、神話、歷史與籃球。此外他還是個電腦游戲高手。您可以通過wuyuehao@cn.ibm.com聯(lián)系到他

    假設(shè)我們有一個簡單的需求,察看一份文檔中 5 個字母組成的單詞的個數(shù)。用 Java 一般實(shí)現(xiàn)如下:

    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;

    public class Find5Words {
    public static void main(String[] args) throws IOException {
    String result = "";
    String line = null;
    int num = 0;
    FileReader fr = new FileReader("filename");
    BufferedReader br = new BufferedReader(fr);
    while ((line = br.readLine()) != null) {
    result += line;
    }
    br.close();
    fr.close();
    String[] s = result.split(" ");
    for (int i = 0; i < s.length; i++) {
    if (s[i].matches("^\\w{5}$")) {
    num++;
    }
    }
    System.out.println(num);
    }
    }

    再看看 Perl 語言實(shí)現(xiàn)同樣功能的代碼:

    open FILE, "<filename ";
    while (<FILE>) {
    for (split) {
    $num++ if /^\w{5}$/
    }
    }
    print $num;

    那么有沒有一種優(yōu)雅的方式將 Java 與腳本語言結(jié)合呢,在今年秋季即將發(fā)布的 Java SE6(代號 Mustang)中,這將成為現(xiàn)實(shí)。





    回頁首


    Mustang 的腳本引擎

    JSR 233 為 Java 設(shè)計了一套腳本語言 API。這一套 API 提供了在 Java 程序中調(diào)用各種腳本語言引擎的接口。任何實(shí)現(xiàn)了這一接口的腳本語言引擎都可以在 Java 程序中被調(diào)用。在 Mustang 的發(fā)行版本中包括了一個基于 Mozilla Rhino 的 JavaScript 腳本引擎。

    Mozilla Rhino

    Rhino 是一個純 Java 的開源的 JavaScript 實(shí)現(xiàn)。他的名字來源于 O'Reilly 關(guān)于 JavaScript 的書的封面:

    Rhino

    Rhino 項(xiàng)目可以追朔到 1997 年,當(dāng)時 Netscape 計劃開發(fā)一個純 Java 實(shí)現(xiàn)的 Navigator,為此需要一個 Java 實(shí)現(xiàn)的 JavaScript —— Javagator。它也就是 Rhino 的前身。起初 Rhino 將 JavaScript 編譯成 Java 的二進(jìn)制代碼執(zhí)行,這樣它會有最好的性能。后來由于編譯執(zhí)行的方式存在垃圾收集的問題并且編譯和裝載過程的開銷過大,不能滿足一些項(xiàng)目的需求,Rhino 提供了解釋執(zhí)行的方式。隨著 Rhino 開放源代碼,越來越多的用戶在自己的產(chǎn)品中使用了 Rhino,同時也有越來越多的開發(fā)者參與了 Rhino 的開發(fā)并做出了很大的貢獻(xiàn)。如今 Rhino1.6R2 版本將被包含在 Java SE6 中發(fā)行,更多的 Java 開發(fā)者將從中獲益。

    Rhino 提供了如下功能

    • 對 JavaScript 1.5 的完全支持
    • 直接在 Java 中使用 JavaScript 的功能
    • 一個 JavaScript shell 用于運(yùn)行 JavaScript 腳本
    • 一個 JavaScript 的編譯器,用于將 JavaScript 編譯成 Java 二進(jìn)制文件

    支持的腳本語言

    dev.java.net可以找到官方的腳本引擎的實(shí)現(xiàn)項(xiàng)目。這一項(xiàng)目基于BSD License ,表示這些腳本引擎的使用將十分自由。目前該項(xiàng)目已對包括 Groovy, JavaScript, Python, Ruby, PHP 在內(nèi)的二十多種腳本語言提供了支持。這一支持列表還將不斷擴(kuò)大。

    在 Mustang 中對腳本引擎的檢索使用了工廠模式。首先需要實(shí)例化一個工廠 —— ScriptEngineManager。

    // create a script engine manager
    ScriptEngineManager factory = new ScriptEngineManager();

    ScriptEngineManager 將在 Thread Context ClassLoader 的 Classpath 中根據(jù) jar 文件的 META-INF 來查找可用的腳本引擎。它提供了 3 種方法來檢索腳本引擎:

    // create engine by name
    ScriptEngine engine = factory.getEngineByName ("JavaScript");
    // create engine by name
    ScriptEngine engine = factory.getEngineByExtension ("js");
    // create engine by name
    ScriptEngine engine = factory.getEngineByMimeType ("application/javascript");

    下面的代碼將會打印出當(dāng)前的 JDK 所支持的所有腳本引擎

    ScriptEngineManager factory = new ScriptEngineManager();
    for (ScriptEngineFactory available : factory.getEngineFactories()) {
    System.out.println(available.getEngineName());
    }

    以下各章節(jié)代碼將以 JavaScript 為例。

    在 Java 中解釋腳本

    有了腳本引擎實(shí)例就可以很方便的執(zhí)行腳本語言,按照慣例,我們還是從一個簡單的 Hello World 開始:

    public class RunJavaScript {
    public static void main(String[] args){
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName ("JavaScript");
    engine.eval("print('Hello World')");
    }
    }

    這段 Java 代碼將會執(zhí)行 JavaScript 并打印出 Hello World。如果 JavaScript 有語法錯誤將會如何?

    engine.eval("if(true){println ('hello')");

    故意沒有加上”}”,執(zhí)行這段代碼 Java 將會拋出一個 javax.script.ScriptException 并準(zhǔn)確的打印出錯信息:
    Exception in thread "main" javax.script.ScriptException: 
    sun.org.mozilla.javascript.internal.EvaluatorException:
    missing } in compound statement (<Unknown source>#1) in <Unknown source>
    at line number 1
    at ...

    如果我們要解釋一些更復(fù)雜的腳本語言,或者想在運(yùn)行時改變該腳本該如何做呢?腳本引擎支持一個重載的 eval 方法,它可以從一個 Reader 讀入所需的腳本:

    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName ("JavaScript");
    engine.eval(new Reader("HelloWorld.js"));

    如此這段 Java 代碼將在運(yùn)行時動態(tài)的尋找 HelloWorld.js 并執(zhí)行,用戶可以隨時通過改變這一腳本文件來改變 Java 代碼的行為。做一個簡單的實(shí)驗(yàn),Java 代碼如下:
    public class RunJavaScript {
    public static void main(String[] args) throws FileNotFoundException,
    ScriptException, InterruptedException {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName ("JavaScript");
    while (true) {
    engine.eval(new FileReader("HelloWorld.js"));
    Thread.sleep(1000);
    }
    }
    }

    HelloWorld.js 內(nèi)容為簡單的打印一個 Hello World: print('Hello World');

    運(yùn)行 RunJavaScript 將會每一秒鐘打印一個 Hello World。這時候修改 HelloWorld.js 內(nèi)容為 print('Hello Tony');

    打印的內(nèi)容將變?yōu)?Hello Tony,由此可見 Java 程序?qū)討B(tài)的去讀取腳本文件并解釋執(zhí)行。對于這一簡單的 Hello World 腳本來說,IO 操作將比直接執(zhí)行腳本損失 20% 左右的性能(在我的 Think Pad 上),但他帶來的靈活性——在運(yùn)行時動態(tài)改變代碼的能力,在某些場合是十分激動人心的。

    腳本語言與 Java 的通信

    ScriptEngine 的 put 方法用于將一個 Java 對象映射成一個腳本語言的變量。現(xiàn)在有一個 Java Class,它只有一個方法,功能就是打印一個字符串 Hello World:

    package tony;

    public class HelloWorld {
    String s = "Hello World";
    public void sayHello(){
    System.out.println(s);
    }
    }

    那么如何在腳本語言中使用這個類呢?put 方法可以做到:

    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;

    public class TestPut {
    public static void main(String[] args) throws ScriptException {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    HelloWorld hello = new HelloWorld();
    engine.put("script_hello", hello);
    engine.eval("script_hello.sayHello()");
    }
    }

    首先我們實(shí)例化一個 HelloWorld,然后用 put 方法將這個實(shí)例映射為腳本語言的變量 script_hello。那么我們就可以在 eval() 函數(shù)中像 Java 程序中同樣的方式來調(diào)用這個實(shí)例的方法。同樣的,假設(shè)我們有一個腳本函數(shù),它進(jìn)行一定的計算并返回值,我們在 Java 代碼中也可以方便的調(diào)用這一腳本:

    package tony;

    import javax.script.Invocable;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;

    public class TestInv {
    public static void main(String[] args) throws ScriptException,
    NoSuchMethodException {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    String script = "function say(first,second) { print(first +' '+ second); }";
    engine.eval(script);
    Invocable inv = (Invocable) engine;
    inv.invokeFunction("say", "Hello", "Tony");
    }
    }

    在這個例子中我們首先定義了一個腳本函數(shù) say,它的作用是接受兩個字符串參數(shù)將他們拼接并返回。這里我們第一次遇到了 ScriptEngine 的兩個可選接口之一 —— Invocable,Invocable 表示當(dāng)前的 engine 可以作為函數(shù)被調(diào)用。這里我們將 engine 強(qiáng)制轉(zhuǎn)換為 Invocable 類型,使用 invokeFunction 方法將參數(shù)傳遞給腳本引擎。invokeFunction這個方法使用了可變參數(shù)的定義方式,可以一次傳遞多個參數(shù),并且將腳本語言的返回值作為它的返回 值。下面這個例子用JavaScript實(shí)現(xiàn)了一個簡單的max函數(shù),接受兩個參數(shù),返回較大的那個。為了便于斷言結(jié)果正確性,這里繼承了JUnit Testcase,關(guān)于JUnit請參考www.junit.org

    package tony;

    import javax.script.Invocable;
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    import junit.framework.TestCase;

    public class TestScripting extends TestCase {

    public void testInv() throws ScriptException, NoSuchMethodException {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    String script = "function max(first,second) "
    + "{ return (first > second) ?first:second;}";
    engine.eval(script);
    Invocable inv = (Invocable) engine;
    Object obj = inv.invokeFunction("max", "1", "0");
    assertEquals("1", obj.toString());
    }
    }

    Invocable 接口還有一個方法用于從一個 engine 中得到一個 Java Interface 的實(shí)例,它的定義如下:

    <T> T getInterface(Class<T> clasz)

    它接受一個 Java 的 Interface 類型作為參數(shù),返回這個 Interface 的一個實(shí)例。也就是說你可以完全用腳本語言來寫一個 Java Interface 的所有實(shí)現(xiàn)。以下是一個例子。 首先定一了個 Java Interface,它有兩個簡單的函數(shù),分別為求最大值和最小值:

    package tony;

    public interface MaxMin {
    public int max(int a, int b);
    public int min(int a, int b);
    }

    這個 Testcase 用 JavaScript 實(shí)現(xiàn)了 MaxMin 接口,然后用 getInterface 方法返回了一個實(shí)例并驗(yàn)證了結(jié)果。

    public void testInvInterface() throws ScriptException,
    NoSuchMethodException {
    ScriptEngineManager factory = new ScriptEngineManager();
    ScriptEngine engine = factory.getEngineByName("JavaScript");
    String script = "function max(first,second) "
    + "{ return (first > second) ?first:second;}";
    script += "function min(first,second) { return (first < second) ?first:second;}";
    engine.eval(script);
    Invocable inv = (Invocable) engine;
    MaxMin maxMin = inv.getInterface(MaxMin.class);
    assertEquals(1, maxMin.max(1, 0));
    assertEquals(0, maxMin.min(1, 0));
    }

    腳本的編譯執(zhí)行

    到目前為止,我們的腳本全部都是解釋執(zhí)行的,相比較之下編譯執(zhí)行將會獲得更好的性能。這里將介紹 ScriptEngine 的另外一個可選接口 —— Compilable,實(shí)現(xiàn)了這一接口的腳本引擎支持腳本的編譯執(zhí)行。下面這個例子實(shí)現(xiàn)了一個判斷給定字符串是否是 email 地址或者 ip 地址的腳本:

    public void testComplie() throws ScriptException {
    ScriptEngineManager manager = new ScriptEngineManager();
    ScriptEngine engine = manager.getEngineByName("JavaScript");
    String script = "var email=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]"
    + "+(\\.[a-zA-Z0-9_-]+)+$/;";
    script += "var ip = /^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])"
    +"(\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])){3}$/;";
    script += "if(email.test(str)){println('it is an email')}"
    + "else if(ip.test(str)){println('it is an ip address')}"
    + "else{println('I don\\'t know')}";
    engine.put("str", "email@address.tony");
    Compilable compilable = (Compilable) engine;
    CompiledScript compiled = compilable.compile(script);
    compiled.eval();
    }

    腳本編譯的過程如下:首先將 engine 轉(zhuǎn)換為 Compilable 接口,然后調(diào)用 Compilable 接口的 compile 方法得到一個 CompiledScript 的實(shí)例,這個實(shí)例就代表一個編譯過的腳本,如此用 CompiledScript 的 eval 方法即為調(diào)用編譯好的腳本了。在我的 Think Pad 上,這段代碼編譯后的調(diào)用大約比直接調(diào)用 engine.eval 要快 3-4 倍。隨著腳本復(fù)雜性的提升,性能的提升會更加明顯。

    腳本上下文與綁定

    真正將腳本語言與 Java 聯(lián)系起來的不是 ScriptEngine,而是 ScriptContext,它作為 Java 與 ScriptEngine 之間的橋梁而存在。

    一個 ScriptEngine 會有一個相應(yīng)的 ScriptContext,它維護(hù)了一個 Map,這個 Map 中的每個元素都是腳本語言對象與 Java 對象之間的映射。同時這個 Map 在我們的 API 中又被稱為 Bindings。一個 Bindings 就是一個限定了 key 必須為 String 類型的 Map —— Map<String, Object>。所以一個 ScriptContext 也會有對應(yīng)的一個 Bindings,它可以通過 getBindings 和 setBindings 方法來獲取和更改。

    一個 Bindings 包括了它的 ScriptContext 中的所有腳本變量,那么如何獲取腳本變量的值呢?當(dāng)然,從 Bindings 中 get 是一個辦法,同時 ScriptContext 也提供了 getAttribute 方法,在只希望獲得某一特定腳本變量值的時候它顯然是十分有效的。相應(yīng)地 setAttribute 和 removeAttribute 可以增加、修改或者刪除一個特定變量。

    在 ScriptContext 中存儲的所有變量也有自己的作用域,它們可以是 ENGINE_SCOPE 或者是 GLOBAL_SCOPE,前者表示這個 ScriptEngine 獨(dú)有的變量,后者則是所有 ScriptEngine 共有的變量。例如我們執(zhí)行 engine.put(key, value) 方法之后,這時便會增加一個 ENGINE_SCOPE 的變量,如果要定義一個 GLOBAL_SCOPE 變量,可以通過 setAttribute(key, value, ScriptContext.GLOBAL_SCOPE) 來完成。

    此外 ScriptContext 還提供了標(biāo)準(zhǔn)輸入和輸出的重定向功能,它可以用于指定腳本語言的輸入和輸出。







    在 JavaScript 中使用 Java 高級特性

    這一部分不同于前述內(nèi)容,將介紹 JavaScript引擎 —— Rhino 獨(dú)有的特性。

    使用 Java 對象

    前面的部分已經(jīng)介紹過如何在 JavaScript 中使用一個已經(jīng)實(shí)例化的 Java 對象,那么如何在 JavaScript 中去實(shí)例化一個 Java 對象呢?在 Java 中所有 Class 是按照包名分層次存放的,而在 JavaScript 沒有這一結(jié)構(gòu),Rhino 使用了一個巧妙的方法實(shí)現(xiàn)了對所有 Java 對象的引用。Rhino 中定義了一個全局變量—— Packages,并且它的所有元素也是全局變量,這個全局變量維護(hù)了 Java 類的層次結(jié)構(gòu)。例如 Packages.java.io.File 引用了 Java 的 io 包中 File 對象。如此一來我們便可以在 JavaScript 中方便的使用 Java 對象了,new 和 Packages 都是可以被省略的:

    //The same as: var frame = new Packages.java.io.File("filename");
    var frame = java.io.File("filename");

    我們也可以像 Java 代碼中一樣把這個對象引用進(jìn)來:

    importClass (java.io.File);
    var file = File("filename");

    如果要將整個包下的所有類都引用進(jìn)來可以用 importPackage:

    importPackage(java.io);

    如果只需要在特定代碼段中引用某些包,可以使用 JavaImporter 搭配 JavaScript 的 with 關(guān)鍵字,如:

    var MyImport = JavaImporter(java.io.File);
    with (MyImport) {
    var myFile = File("filename");
    }

    用戶自定義的包也可以被引用進(jìn)來,不過這時候 Packages 引用不能被省略:

    importPackage(Packages.tony);
    var hello = HelloWorld();
    hello.sayHello();

    注意這里只有 public 的成員和方法才會在 JavaScript 中可見,例如對 hello.s 的引用將得到 undefined。下面簡單介紹一些常用的特性:

    使用 Java 數(shù)組

    需要用反射的方式構(gòu)造:

    var a = java.lang.reflect.Array.newInstance(java.lang.String, 5);

    對于大部分情況,可以使用 JavaScript 的數(shù)組。將一個 JavaScript 的數(shù)組作為參數(shù)傳遞給一個 Java 方法時 Rhino 會做自動轉(zhuǎn)換,將其轉(zhuǎn)換為 Java 數(shù)組。

    實(shí)現(xiàn)一個 Java 接口

    除了上面提到的 Invocable 接口的 getInterface 方法外,我們也可以在腳本中用如下方式:

    //Define a JavaScript Object which has corresponding method
    obj={max:function(a,b){return (a > b) ?a:b;}};
    //Pass this object to an Interface
    maxImpl=com.tony.MaxMin(obj);
    //Invocation
    print (maxImpl.max(1,2));

    如果接口只有一個方法需要實(shí)現(xiàn),那么在 JavaScript 中你可以傳遞一個函數(shù)作為參數(shù):

    function func(){
    println("Hello World");
    }
    t=java.lang.Thread(func);
    t.start();

    對于 JavaBean 的支持

    Rhino 對于 JavaBean 的 get 和 is 方法將會自動匹配,例如調(diào)用 hello.string,如果不存在 string 這個變量,Rhino 將會自動匹配這個實(shí)例的 isString 方法然后再去匹配 getString 方法,若這兩個方法均不存在才會返回 undefined。








    命令行工具 jrunscript

    在 Mustang 的發(fā)行版本中還將包含一個腳本語言的的命令行工具,它能夠解釋所有當(dāng)前 JDK 支持的腳本語言。同時它也是一個用來學(xué)習(xí)腳本語言很好的工具。你可以在http://java.sun.com/javase/6/docs/technotes/tools/share/jrunscript.html找到這一工具的詳細(xì)介紹。








    結(jié)束語

    腳本語言犧牲執(zhí)行速度換來更高的生產(chǎn)率和靈活性。隨著計算機(jī)性能的不斷提高,硬件價格不斷下降,可以預(yù)見的,腳本語言將獲得更廣泛的應(yīng)用。在 JavaSE 的下一個版本中加入了對腳本語言的支持,無疑將使 Java 程序變得更加靈活,也會使 Java 程序員的工作更加有效率。



    參考資料


    posted on 2007-02-08 11:18 wqwqwqwqwq 閱讀(2037) 評論(1)  編輯  收藏 所屬分類: SUN Tech

    FeedBack:
    # re: Java6 MUstang新特性總結(jié)(摘錄)
    2010-07-22 13:40 | ed hardy
    Thanks for your sharing.I like it very much, thanks!  回復(fù)  更多評論
      
    <2007年2月>
    28293031123
    45678910
    11121314151617
    18192021222324
    25262728123
    45678910




    常用鏈接

    留言簿(10)

    隨筆分類(95)

    隨筆檔案(97)

    文章檔案(10)

    相冊

    J2ME技術(shù)網(wǎng)站

    java技術(shù)相關(guān)

    mess

    搜索

    •  

    最新評論

    閱讀排行榜

    校園夢網(wǎng)網(wǎng)絡(luò)電話,中國最優(yōu)秀的網(wǎng)絡(luò)電話
    主站蜘蛛池模板: 免费99精品国产自在现线| 久久一本岛在免费线观看2020| 男女男精品网站免费观看| 黄色一级毛片免费| 91免费在线视频| 3d成人免费动漫在线观看| 在线观看AV片永久免费| 免费国产高清视频| 久久久久亚洲?V成人无码| 久久精品国产亚洲av麻豆色欲| 亚洲一欧洲中文字幕在线| 豆国产96在线|亚洲| 拍拍拍无挡免费视频网站| 亚洲综合免费视频| 在线观看91精品国产不卡免费| ZZIJZZIJ亚洲日本少妇JIZJIZ| 久久精品国产亚洲AV果冻传媒| 亚洲国产精品线观看不卡| 亚洲av成人片在线观看| 中文字幕免费在线看| 久热中文字幕在线精品免费| 国产一区二区三区在线免费观看| 亚洲自偷自偷图片| 亚洲一区二区三区亚瑟| 成人免费网站视频www| 最近中文字幕高清免费中文字幕mv| 暖暖免费高清日本中文| 亚洲精品国偷自产在线| 亚洲综合欧美色五月俺也去| 国产高清视频免费在线观看| 特级做A爰片毛片免费69| 亚洲国产精品成人| 亚洲人成在线精品| 中国一级特黄的片子免费 | 又粗又硬又黄又爽的免费视频 | 日韩毛片免费一二三| 69av免费视频| 国产成人综合亚洲AV第一页| 亚洲欧洲另类春色校园网站| 国产美女视频免费观看的网站 | 国产无遮挡吃胸膜奶免费看视频|