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

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

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

    afunms

    My Software,My Dream—Forge a more perfect NMS product.

    充分利用Java元數(shù)據(jù)

    http://www.oracle.com/technology/global/cn/pub/articles/hunter_meta.html

    了解如何使用 J2SE 5.0 中提供的元數(shù)據(jù)批注

    最新的 J2SE 5.0 版本(也以代號(hào) "Tiger" 著稱)為 Java 語(yǔ)言引進(jìn)了許多變化,這些變化旨在使 Java 編程更有表現(xiàn)力、更加開發(fā)人員友好和更安全。我在 2003 年 9 月的一篇題目為“Java 即將發(fā)生巨大變化”的文章中介紹了許多 Java 新特性。我沒有介紹的一個(gè)重大的變化 — 那時(shí)還沒有完整概述它 — 是 Java 的元數(shù)據(jù)工具。從本文開始,在一個(gè)新的分為四個(gè)部分的文章系列中,我將從一年前離開的地方繼續(xù)向您顯示如何充分利用 Java 的元數(shù)據(jù)。

    在第一篇文章中,我將說明元數(shù)據(jù)的用途并演示如何使用在核心的 J2SE 資料庫(kù)中提供的元數(shù)據(jù)批注。

    在第二篇文章中,我將顯示如何編寫您自己的批注(首先編寫類似 @Copyright 的簡(jiǎn)單的批注,然后看看與核心語(yǔ)言中內(nèi)置的那些批注類似的更高級(jí)的批注)。

    在第三篇文章中,我將演示工具如何在構(gòu)建時(shí)使用批注(創(chuàng)建新的源文件或支持文件)以及程序如何在運(yùn)行時(shí)使用批注(以改變代碼的行為)。

    在最后的第四篇文章中,我將介紹如何利用在 JSR-181 下開發(fā)的標(biāo)準(zhǔn)元數(shù)據(jù)批注的幫助使編輯和部署 Web 服務(wù)在未來變得更容易(Oracle 是 JSR-181 的專家組的成員,并且是在開發(fā)工具中增加對(duì)設(shè)計(jì)時(shí)元數(shù)據(jù)的支持的一個(gè)積極的擁護(hù)者。)

    元數(shù)據(jù)

    我承認(rèn)當(dāng)我第一次看到 JSR-175 的提案“用于 Java 編程語(yǔ)言的元數(shù)據(jù)工具”(在 2004 年 9 月發(fā)布;Oracle 也是該專家組的成員)時(shí),我預(yù)測(cè)它將創(chuàng)建必須放在 JAR 的 META-INF 目錄下的另一個(gè)屬性文件,或者必須與 JAR 捆綁的另一個(gè) XML 部署描述符。幸運(yùn)的是,這不是元數(shù)據(jù)要做的。事實(shí)上,它正好相反。Java 的新的元數(shù)據(jù)工具提供了從 Java 代碼內(nèi)部批注 Java 代碼的一種標(biāo)準(zhǔn)方式。它使您能夠在要說明的元素的旁邊放置描述性的元數(shù)據(jù)。

    當(dāng)討論元數(shù)據(jù)時(shí),您將經(jīng)常看到幾個(gè)類似的術(shù)語(yǔ),因此下面提供了一個(gè)小術(shù)語(yǔ)表來幫助您了解它們的差異:

    術(shù)語(yǔ) 定義
    元數(shù)據(jù) 關(guān)于數(shù)據(jù)的數(shù)據(jù)。JSR-175 的目標(biāo)是在 Java 語(yǔ)言中提供元數(shù)據(jù)工具。
    批注 一種特殊的 Java 結(jié)構(gòu),用來修飾類、方法、字段、參數(shù)、變量、構(gòu)造器或包。它是 JSR-175 選擇用來提供元數(shù)據(jù)的工具。
    批注類型 具有特殊實(shí)施的各種命名批注
    屬性 由批注指定的一個(gè)特殊的元數(shù)據(jù)項(xiàng)目。有時(shí)可以和批注交替使用

     

    例如:富士蘋果有一個(gè)屬性:它是紅色的。假定有一個(gè) FujiApple 類,您可以使用 @Color 批注類型的一個(gè)批注來指定它的顏色。通過這么做,您就提供了關(guān)于蘋果的元數(shù)據(jù)。

    自 1.0 版以來在 Java 中一直存在對(duì)元數(shù)據(jù)的需求。Java 從來沒有提供記錄元數(shù)據(jù)的標(biāo)準(zhǔn)機(jī)制,因而我們編程人員找到了各種技巧和竅門使用任意的工具來添加元數(shù)據(jù)。您看到在 J2SE 1.4 和更低版本中使用元數(shù)據(jù)的一些地方有:

    • transient 關(guān)鍵字
    • Serializable 標(biāo)記接口
    • SingleThreadModel servlet 接口
    • web.xml 部署描述符內(nèi)部的元素
    • META-INF/MANIFEST.MF 文件
    • BeanInfo 接口
    • @deprecated Javadoc 注釋
    • 所有的 XDoclet Javadoc 標(biāo)記。

     

    當(dāng)使用這些技巧時(shí),您可能沒有想到您正在添加元數(shù)據(jù),但事實(shí)上您的確在添加元數(shù)據(jù)。上述方法存在的問題是它們都是解決同一問題的不同方法,但通用性不好。每一種方法都至少有一個(gè)缺點(diǎn)在新的元數(shù)據(jù)工具中得到了解決。

    對(duì)于這個(gè)列表中的一些方法,局限很明顯。使用關(guān)鍵字不能伸縮;您不能使用用戶自己定義的關(guān)鍵字。標(biāo)記接口沒有提供除它們的存在性之外的任何信息(即,它們沒有帶參數(shù)),并且它們只能處理類,而不能處理字段或方法或包。

    列表中的其他一些方法可能看起來合理。使用 XML 支持文件似乎是個(gè)好主意,而事實(shí)上在許多情況下仍是個(gè)好主意。但對(duì)于我們使用 XML 文件的許多用途,例如指示類的哪一個(gè)方法應(yīng)當(dāng)看作是 web 服務(wù),在 Java 代碼內(nèi)部將規(guī)則直接放在方法的旁邊將更加高效。利用元數(shù)據(jù),您可以使 XML 描述符文件僅包含與部署相關(guān)的決策。

    該列表中可能最高效的元數(shù)據(jù)的用法是 @deprecated Javadoc 注釋和在其鏡像中創(chuàng)建的 XDoclet 標(biāo)記。這可能是 JSR-175 語(yǔ)法為什么看起來與 @deprecated 標(biāo)記非常類似的原因(正如我們將在下一部分中看到的那樣)。

    批注

    批注可以很容易地附加到代碼結(jié)構(gòu)上。您可以寫一個(gè) "at" 符號(hào) (@),然后是批注類型名稱,并將批注直接放在要批注的項(xiàng)目前面。下面是一個(gè)簡(jiǎn)單的例子:

    import javax.jws.WebService;
    import javax.jws.WebMethod;
    @WebService
    public class HelloWorldService {
    @WebMethod
    public String helloWorld() {
    return "Hello World!";
    }
    }
    

     

    當(dāng)部署在正確的環(huán)境中時(shí),增加 @WebService@WebMethod 批注將指示 web 服務(wù)環(huán)境將該類變?yōu)?web 服務(wù)。

    您可以批注方法、類、字段、參數(shù)、變量、構(gòu)造器甚至整個(gè)包(利用一個(gè)特殊的外部 package-info.java 文件)。批注可以在括號(hào)內(nèi)帶任意數(shù)量的命名參數(shù)。下面是使用批注進(jìn)行修飾以創(chuàng)建 web 服務(wù)的一個(gè)更高級(jí)的示例類。它包含了一個(gè)理論上的 JNDI 環(huán)境變量查找:

    @WebService(
    name = "PingService",
    targetNamespace="http://acme.com/ping"
    )
    @SOAPBinding(
    style=SOAPBinding.Style.RPC,
    use=SOAPBinding.Use.LITERAL
    )
    public class Ping {
    public @env double level = 500.0;  // JNDI lookup
    public @WebMethod(operationName = "Foo") {
    void foo() { }
    }
    }
    

     

    這個(gè)例子顯示了附加到類、變量和方法(在類上實(shí)際上有兩個(gè)方法)上的批注。@env 批注沒有任何參數(shù),因此它不需要括號(hào)。其他批注有一個(gè)或更多的命名參數(shù)。

    當(dāng)創(chuàng)建新的批注類型時(shí),您將限定允許哪些參數(shù)名以及它們的類型。批注接受的類型是嚴(yán)格限定的;它們只可以是基本類型、String、Class、枚舉類型、批注類型和前面這些類型的數(shù)組。傳遞的參數(shù)必須始終是非空的編譯時(shí)常量。

    要了解本示例中顯示的批注有什么效果必須等到本系列的第四篇文章。讓我們開始看看 J2SE 5.0 提供的簡(jiǎn)單的批注類型:@Override、@Deprecated@SuppressWarnings。

    內(nèi)置的批注

    當(dāng)我們看這三種標(biāo)準(zhǔn)的用戶級(jí)批注時(shí),必須考慮:在可以提供的所有可能的批注類型中,為什么 Tiger 恰恰提供三種?原因是提供大量的標(biāo)準(zhǔn)批注并不是目標(biāo)所在。

    JSR-175 的宗旨嚴(yán)格規(guī)定了它是要定義一個(gè)元數(shù)據(jù)工具。編寫自定義批注類型的任務(wù)留給了編程人員,而編寫一組標(biāo)準(zhǔn)的批注類型的任務(wù)留給了其他 JSR。例如,有一個(gè)新的名稱為“Java 平臺(tái)的通用批注”的 JSR-250,其宗旨是“為 J2SE 和 J2EE 平臺(tái)中的通用的語(yǔ)義概念開發(fā)適用于各種技術(shù)的批注”。JSR-250 計(jì)劃在 2005 年春天的某個(gè)時(shí)候在 javax.annotations 程序包中提供它的標(biāo)準(zhǔn)的批注集。還有之前提到的 JSR-181,它將使得在 J2EE 容器中編寫 Web 服務(wù)變得更容易(我們將在本系列中的第四篇文章中進(jìn)行介紹)。事實(shí)上,大多數(shù)新的企業(yè) JSR(從 Servlets 2.5 到 EJB 3.0 到 JDBC 4.0)都在考慮批注可以提供哪些優(yōu)點(diǎn)。

    @Override

    第一個(gè) J2SE 標(biāo)準(zhǔn)批注 @Override 使您能夠在代碼中增加新的可選的編譯器檢查。它在方法中存在表示該方法用于覆蓋父類中的方法。如果編譯器檢測(cè)到該方法實(shí)際上沒有覆蓋任何東西,那么將出現(xiàn)編譯錯(cuò)誤。經(jīng)常使用,@Override 可以幫助您避免當(dāng)方法標(biāo)記沒有完全匹配時(shí) — 當(dāng)多態(tài)變?yōu)椋梢苑Q之為)“單態(tài)” ("unimorphism") 時(shí) — 將得到的細(xì)微的 bug。

    例如,以下代碼可能看起來很合理:

    public class OverrideExample {
    @Override
    public boolean equals(OverrideExample obj) {
    return false;
    }
    }
    

     

    然而,當(dāng)您編譯 OverrideExample.java 時(shí),您將得到一個(gè)錯(cuò)誤,該錯(cuò)誤指示一個(gè)細(xì)微的問題。

    % javac OverrideExample.java
    javac OverrideExample.java
    OverrideExample.java:3: method does not override a method from its superclass
    @Override
    ^
    1 error
    

     

    通過提示編譯器您希望進(jìn)行覆蓋,使編譯器能夠捕獲到 equals() 方法帶 Object 類型參數(shù)的細(xì)微 bug。

    @Override 批注在實(shí)際中有用嗎?只有當(dāng)您是一個(gè)愿意用 @Override 來標(biāo)記每一個(gè)覆蓋方法的非常嚴(yán)謹(jǐn)?shù)木幊倘藛T時(shí)才有用。我們中有多少人能聲稱可以達(dá)到這種嚴(yán)謹(jǐn)程度?我認(rèn)為我不能。可能 IDE 將找到一種方式來鼓勵(lì)或強(qiáng)制使用 @Override。

    @Deprecated

    第二種標(biāo)準(zhǔn)批注是 @Deprecated,它與 @deprecated Javadoc 標(biāo)記有幾乎相同的行為。您可以用類似以下的方式來使用它:

    public class DeprecatedExample {
    @Deprecated
    public static void badMethod() {
    }
    }
    public class DeprecatedUser {
    public static void main(String[] args) {
    DeprecatedExample.badMethod();
    }
    }
    

     

    The @Deprecated 批注看起來非常像 @deprecated 標(biāo)記,除了它出現(xiàn)在注釋外面的方法或類聲明的前面,并且有一個(gè)大寫字母 "D"。如果您試圖編譯上面的代碼,javac 將產(chǎn)生警告:

    % javac Deprecated*.java
    Note:DeprecatedUser.java uses or overrides a deprecated API.
    Note:Recompile with -Xlint:deprecation for details.
    1 error
    

     

    如果您遵循警告的建議并用 -Xlint:deprecation 進(jìn)行編譯,那么您將得到關(guān)于警告的詳細(xì)信息:

    % javac -Xlint:deprecation
    DeprecatedUser.java:3: warning: [deprecation] badMethod() in DeprecatedExample
    has been deprecated
    DeprecatedExample.badMethod();
    

     

    @Deprecated 批注比 @Override 更有用嗎?我不這么認(rèn)為。該批注不支持任何參數(shù),因此與 Javadoc 標(biāo)記不同,您不能提供一個(gè)字符串來說明不贊成使用該方法并推薦一個(gè)替代的方法進(jìn)行使用。@Deprecated 批注提供的價(jià)值實(shí)際上比 @deprecated 標(biāo)記少。該批注唯一的優(yōu)勢(shì)是您可以通過編程的方式在運(yùn)行時(shí)檢測(cè)不贊成使用的項(xiàng)目。因此,傳統(tǒng)觀點(diǎn)認(rèn)為應(yīng)當(dāng)同時(shí)使用 @deprecated 標(biāo)記和 @Deprecated 標(biāo)記,一個(gè)用于文檔,另一個(gè)用于運(yùn)行時(shí)反射。

    我覺得很不幸 JSR-175 沒有選擇對(duì) @Deprecated 做更多的工作。至少該批注應(yīng)當(dāng)復(fù)制 @deprecated 標(biāo)記的功能,包含一個(gè)字符串說明,從而編譯器可以將其與“不贊成使用” (Deprecation) 警告一起輸出。利用額外的參數(shù),@Deprecated 還可以接收 "isError" 布爾類型參數(shù),以指示是否完全不鼓勵(lì)使用該方法或者使用它將被認(rèn)為是編譯錯(cuò)誤(利用解釋錯(cuò)誤原因的清楚的自定義說明來進(jìn)行完善)。查看 C# 的示例 1 找到屬性 [Obsolete],該屬性正好實(shí)現(xiàn)了這一點(diǎn),它被證明非常有用。

    @SuppressWarnings

    J2SE 提供的最后一個(gè)批注是 @SuppressWarnings。該批注的作用是給編譯器一條指令,告訴它對(duì)被批注的代碼元素內(nèi)部的某些警告保持靜默。

    一點(diǎn)背景:J2SE 5.0 為 Java 語(yǔ)言增加了幾個(gè)新的特性,并且和它們一起增加了許多新的警告并承諾在將來增加更多的警告。您可以為 "javac" 增加 -Xlint 參數(shù)來控制是否報(bào)告這些警告(如上面的 @Deprecated 部分所示)。

    默認(rèn)情況下,Sun 編譯器以簡(jiǎn)單的兩行的形式輸出警告。通過添加 -Xlint:keyword 標(biāo)記(例如 -Xlint:finally),您可以獲得關(guān)鍵字類型錯(cuò)誤的完整說明。通過在關(guān)鍵字前面添加一個(gè)破折號(hào),寫為 -Xlint:-keyword,您可以取消警告。(-Xlint 支持的關(guān)鍵字的完整列表可以在 javac 文檔頁(yè)面上找到。)下面是一個(gè)清單:

    關(guān)鍵字 用途
    deprecation 使用了不贊成使用的類或方法時(shí)的警告
    unchecked 執(zhí)行了未檢查的轉(zhuǎn)換時(shí)的警告,例如當(dāng)使用集合時(shí)沒有用泛型 (Generics) 來指定集合保存的類型。
    fallthrough 當(dāng) Switch 程序塊直接通往下一種情況而沒有 Break 時(shí)的警告。
    path 在類路徑、源文件路徑等中有不存在的路徑時(shí)的警告。
    serial 當(dāng)在可序列化的類上缺少 serialVersionUID 定義時(shí)的警告。
    finally 任何 finally 子句不能正常完成時(shí)的警告。
    all 關(guān)于以上所有情況的警告。

     

    @SuppressWarnings 批注允許您選擇性地取消特定代碼段(即,類或方法)中的警告。其中的想法是當(dāng)您看到警告時(shí),您將調(diào)查它,如果您確定它不是問題,您就可以添加一個(gè) @SuppressWarnings 批注,以使您不會(huì)再看到警告。雖然它聽起來似乎會(huì)屏蔽潛在的錯(cuò)誤,但實(shí)際上它將提高代碼安全性,因?yàn)樗鼘⒎乐鼓鷮?duì)警告無(wú)動(dòng)于衷 — 您看到的每一個(gè)警告都將值得注意。

    下面是使用 @SuppressWarnings 來取消 deprecation 警告的一個(gè)例子:

    public class DeprecatedExample2 {
    @Deprecated
    public static void foo() {
    }
    }
    public class DeprecatedUser2 {
    @SuppressWarnings(value={"deprecation"})
    public static void main(String[] args) {
    DeprecatedExample2.foo();
    }
    }
    

     

    @SuppressWarnings 批注接收一個(gè) "value" 變量,該變量是一個(gè)字符串?dāng)?shù)組,它指示將取消的警告。合法字符串的集合隨編譯器而變化,但在 JDK 上,可以傳遞給 -Xlint 的是相同的關(guān)鍵字集合(非常方便)。并且要求編譯器忽略任何它們不能識(shí)別的關(guān)鍵字,這在您使用一些不同的編譯器時(shí)非常方便。

    因?yàn)?@SuppressWarnings 批注僅接收一個(gè)參數(shù),并為該參數(shù)使用了特殊的名稱 "value",所以您可以選擇省略 value=,作為一種方便的縮寫:

    public class DeprecatedUser2 {
      @SuppressWarnings({"deprecation"})
    public static void main(String[] args) {
        DeprecatedExample2.foo();
      }
    }

    您可以將單個(gè)數(shù)組參數(shù)中的任意數(shù)量的字符串值傳遞給批注,并在任何級(jí)別上放置批注。例如,以下示例代碼指示將取消整個(gè)類的 deprecation 警告,而僅在 main() 方法代碼內(nèi)取消 unchecked 和 fallthrough 警告:

    import java.util.*;

    @SuppressWarnings({"deprecation"})
    public class NonGenerics {

      @SuppressWarnings({"unchecked","fallthrough"})
    public static void main(String[] args) {
        Runtime.runFinalizersOnExit();

        List list = new ArrayList();
        list.add("foo");
      }

      public static void foo() {
        List list = new ArrayList();
        list.add("foo");
      }
    }

    @SuppressWarnings 是否比前兩個(gè)批注更有用?絕對(duì)是這樣。不過,在 JDK 1.5.0 版本中還沒有完全支持該批注,如果您用 1.5.0 來嘗試它,那么它將類似無(wú)操作指令。調(diào)用 -Xlint:-deprecation 也沒有任何效果。Sun 沒有聲明什么時(shí)候?qū)⒃黾又С?,但它暗示這將在即將推出的一個(gè) dot 版本中實(shí)現(xiàn)。

    posted on 2008-10-01 14:12 afunms 閱讀(269) 評(píng)論(0)  編輯  收藏


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    My Links

    News

    留言簿(18)

    隨筆檔案

    相冊(cè)

    搜索

    最新評(píng)論

    閱讀排行榜

    主站蜘蛛池模板: 成人在线免费观看| 亚洲乱码中文字幕久久孕妇黑人 | 中文字幕一区二区免费| 一个人看www在线高清免费看 | 亚洲av极品无码专区在线观看| 一级黄色免费毛片| 浮力影院第一页小视频国产在线观看免费| 久久亚洲综合色一区二区三区| 手机永久免费的AV在线电影网| 四虎精品亚洲一区二区三区| 亚洲色无码专区一区| 无码少妇一区二区浪潮免费| 国产成人无码精品久久久久免费| 亚洲男人的天堂一区二区| 国产AV无码专区亚洲AV琪琪| 免费无码黄十八禁网站在线观看| 久久精品亚洲AV久久久无码| 亚洲中文字幕无码不卡电影| av电影在线免费看| 亚洲人xxx日本人18| 免费视频中文字幕| 国产精品免费高清在线观看| 亚洲avav天堂av在线不卡| a级午夜毛片免费一区二区| 亚洲国产日韩精品| 国产aa免费视频| 日本激情猛烈在线看免费观看| 亚洲精品无码激情AV| 成年性生交大片免费看| 免费在线看污视频| 亚洲日韩区在线电影| 无码av免费毛片一区二区| 一本天堂ⅴ无码亚洲道久久| 亚洲国产日韩一区高清在线 | 亚洲人成影院在线无码观看| 国产啪精品视频网站免费尤物| 亚洲国产精品不卡在线电影| 亚洲国产人成精品| 久久精品无码专区免费东京热| 久久精品国产亚洲AV忘忧草18| 亚洲AV人人澡人人爽人人夜夜|