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

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

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

    gembin

    OSGi, Eclipse Equinox, ECF, Virgo, Gemini, Apache Felix, Karaf, Aires, Camel, Eclipse RCP

    HBase, Hadoop, ZooKeeper, Cassandra

    Flex4, AS3, Swiz framework, GraniteDS, BlazeDS etc.

    There is nothing that software can't fix. Unfortunately, there is also nothing that software can't completely fuck up. That gap is called talent.

    About Me

     

    在Java1.5中創(chuàng)建可變參數(shù)[Varargs]

    方法重載是Java和其他面向?qū)ο笳Z言最具特色的特性之一。當(dāng)許多人可能認(rèn)為Java的優(yōu)勢是它的類型,或者是它所帶的API庫,其實讓相同的方法名與各種各樣可接受的參數(shù)搭配也是一件很好的事。

    Guitar guitar = new Guitar("Bourgeois", "Country Boy Deluxe",
    GuitarWood.MAHOGANY, GuitarWood.ADIRONDACK,1.718);
    Guitar guitar = new Guitar("Martin", "HD-28");
    Guitar guitar = new Guitar("Collings", "CW-28"
    GuitarWood.BRAZILIAN_ROSEWOOD, GuitarWood.ADIRONDACK,1.718,
    GuitarInlay.NO_INLAY, GuitarInlay.NO_INLAY);

    This code calls three versions of the constructor of a (fictional) Guitar class, meaning that information can be supplied when it’s available,rather than forcing a user to know everything about their guitar at one time (many professionals couldn’t tell you their guitar’s width at the nut).
    Here are the constructors used:
    public Guitar(String builder, String model) {
    }
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,
    float nutWidth) {
    }
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,
    float nutWidth,
    GuitarInlay fretboardInlay, GuitarInlay topInlay) {
    }

      這段代碼調(diào)用了Guitar類中三個版本的構(gòu)造器,意味著當(dāng)信息可見時,這些信息會被支持,而不是迫使每一個使用者每一次都要去了解關(guān)于Guitar類的所有知識。許多專家不會在關(guān)鍵時候告訴你他們的Guitar的內(nèi)容。下面是用到的構(gòu)造器:

    public Guitar(String builder, String model) {
    }
    public Guitar(String builder, String model,GuitarWood backSidesWood, GuitarWood topWood,float nutWidth) {
    }
    public Guitar(String builder, String model,GuitarWood backSidesWood, GuitarWood topWood,float nutWidth,
    GuitarInlay fretboardInlay, GuitarInlay topInlay) {
    }

      然而,當(dāng)你想要去增加無限的信息時,事情開始變得有一點不是那么有用了。例如:假設(shè)你想允許在這個構(gòu)造器中增加額外的未指明的特性。下面就是一些可能的調(diào)用的例子:

    Guitar guitar = new Guitar("Collings", "CW-28"
    GuitarWood.BRAZILIAN_ROSEWOOD, GuitarWood.ADIRONDACK,1.718,
    GuitarInlay.NO_INLAY, GuitarInlay.NO_INLAY,"Enlarged Soundhole", "No Popsicle Brace");
    Guitar guitar = new Guitar("Martin", "HD-28V","Hot-rodded by Dan Lashbrook", "Fossil Ivory Nut","Fossil Ivory Saddle", "Low-profile bridge pins");

      對于這兩個單獨的情況,你不得不去增加一個構(gòu)造器來接受兩個額外的字符串,另外一個構(gòu)造器來接受四個額外的字符串。試圖將這些相似的版本應(yīng)用于早已重載的構(gòu)造器。根據(jù)這樣的話,你最終會得到20或30個那樣愚蠢的構(gòu)造器的版本!

      原因在于我們常稱做的可變參數(shù)。可變參數(shù)是Tiger的增加的另一個特性,它用一種相當(dāng)巧妙的方法徹底地解決了這兒提出的問題。這一章講述了這種相對簡單的特性的各個方面。這將會使你迅速寫出更好、更整潔、更靈活的代碼。

      創(chuàng)建一個可變長度的參數(shù)列表

      可變參數(shù)使得你可以指定某方法來接受多個同一類型的參數(shù),而且并不要求事先確定參數(shù)的數(shù)量(在編譯或運行時)。

      這就是Tiger的一個集成部分。事實上,正是因為Java語言的一些新特性組合在一起才表現(xiàn)出了可變參數(shù)的特性。

      我如何去實現(xiàn)呢?

      首先,你要習(xí)慣的書寫省略號(……)。這三個小點是可變參數(shù)的關(guān)鍵,你將會經(jīng)常鍵入它們。下面是Guitar類的構(gòu)造器使用可變參數(shù)來接受不確定數(shù)量字符串的一個例子:

    public Guitar(String builder, String model, String……features);

      參數(shù)String…… features 表明任何數(shù)量的字符串都可能被接受。 所以,下面所有的調(diào)用都合法的。

    Guitar guitar = new Guitar("Martin", "HD-28V","Hot-rodded by Dan Lashbrook", "Fossil Ivory Nut","Fossil Ivory Saddle", "Low-profile bridge pins");
    Guitar guitar = new Guitar("Bourgeois", "OMC","Incredible flamed maple bindings on this one.");
    Guitar guitar = new Guitar("Collings", "OM-42","Once owned by Steve Kaufman--one of a kind");
    You could add the same variable-length argument to the other constructors:
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,float nutWidth, String... features)
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,float nutWidth,
    GuitarInlay fretboardInlay,GuitarInlay topInlay,String... features)

      例5-1描寫了一個把所有的這些特性放在一起的簡單類,甚至使用XX來一起傳遞一些可變參數(shù)。

      Example 5-1. Using varargs in constructors

    package com.oreilly.tiger.ch05;
    public class Guitar {
    private String builder;
    private String model;
    private float nutWidth;
    private GuitarWood backSidesWood;
    private GuitarWood topWood;
    private GuitarInlay fretboardInlay;
    private GuitarInlay topInlay;
    private static final float DEFAULT_NUT_WIDTH = 1.6875f;
    public Guitar(String builder, String model, String... features) {
    this(builder, model, null, null, DEFAULT_NUT_WIDTH, null, null, features);
    }
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,
    float nutWidth, String... features) {
    this(builder, model, backSidesWood, topWood, nutWidth, null, null, features);
    }
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,float nutWidth,
    GuitarInlay fretboardInlay, GuitarInlay topInlay,String... features) {
    this.builder = builder;
    this.model = model;
    this.backSidesWood = backSidesWood;
    this.topWood = topWood;
    this.nutWidth = nutWidth;
    this.fretboardInlay = fretboardInlay;
    this.topInlay = topInlay;
    }
    }

      剛才發(fā)生了什么?

      當(dāng)你指定了一個可變長度參數(shù)列表,Java編譯器實際上讀入 “create an array of type <參數(shù)類型>”。你鍵入:

    public Guitar(String builder, String model, String…… features)

      然而:編譯器解釋這些為:

    public Guitar(String builder, String model, String[] features)

      這意味著重復(fù)參數(shù)列表變得簡單(這將在“重復(fù)可變長度參數(shù)列表”里講述),這與你需要完成的其他程序設(shè)計目標(biāo)是一樣。

      你可以像使用數(shù)組一樣來使用可變參數(shù)。

      然而,這同樣存在一些限制。第一,在每個方法中,你只可以使用一次省略號。所以,下面的書寫是不合法的:
    public Guitar(String builder, String model,String…… features, float…… stringHeights)

      另外,省略號必須作為方法的最后一個參數(shù)。

      如果你不需要傳遞任何可變參數(shù)呢?

      那沒關(guān)系,你只需要以舊的方式調(diào)用構(gòu)造器:

    Guitar guitar = new Guitar("Martin", "D-18");

      我們再仔細(xì)看看,雖然程序中沒有與下面代碼相匹配的構(gòu)造器:

    public Guitar(String builder, String model)

      那么,代碼到底傳遞了什么呢?作為可變參數(shù)的特例,在參數(shù)中不傳遞東西是一個合法的選項。所以,當(dāng)你看到 String…… features,你應(yīng)該把它認(rèn)為是零個或者更多個String參數(shù)。這省卻你再去創(chuàng)建另一個不帶可變參數(shù)構(gòu)造器的麻煩。

      重復(fù)可變長度參數(shù)類表

      所有這些可變參數(shù)是很好的。但是實際上,如果你不在你的方法中使用它們的話,他們顯然僅僅是吸引眼球的東西或是窗戶的裝飾品而已。

      然而,你可以像你使用數(shù)組一樣來使用可變參數(shù),你會覺得這種用法很簡單。

      那我怎么來使用可變參數(shù)呢?

      首先你要確保閱讀了“創(chuàng)建一個可變長度的參數(shù)列表”,你會從中了解到可變參數(shù)方法最重要的東西,那就是我們把可變參數(shù)當(dāng)作數(shù)組來看待。

      所以,繼續(xù)前面的例子,你可以寫出下面的代碼:

    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,float nutWidth,
    GuitarInlay fretboardInlay, GuitarInlay topInlay,String... features) {
    this.builder = builder;
    this.model = model;
    this.backSidesWood = backSidesWood;
    this.topWood = topWood;
    this.nutWidth = nutWidth;
    this.fretboardInlay = fretboardInlay;
    this.topInlay = topInlay;
    for (String feature : features) {
    System.out.println(feature);
    }
    }

      上面的這段代碼看上是不是不是那么的有吸引力?但這確實體現(xiàn)了可變參數(shù)的精髓。作為另一個例子,下面這個簡單的方法從一組數(shù)字中計算出最大值:

    public static int max(int first, int... rest) {
    int max = first;
    for (int i : rest) {
    if (i > max)
    max = i;
    }
    return max;
    }

      是不是,夠簡單吧?

      那么如何存儲可變長度參數(shù)呢?

      正因為Java編譯器把這些看作數(shù)組,所以數(shù)組顯然是一個存儲的好選擇,這將在下面的例5-2中體現(xiàn)。

      Example 5-2. 存儲作為成員變量的可變參數(shù)

    package com.oreilly.tiger.ch05;
    public class Guitar {
    private String builder;
    private String model;
    private float nutWidth;
    private GuitarWood backSidesWood;
    private GuitarWood topWood;
    private GuitarInlay fretboardInlay;
    private GuitarInlay topInlay;
    private String[] features;
    private static final float DEFAULT_NUT_WIDTH = 1.6875f;
    public Guitar(String builder, String model, String... features) {
    this(builder, model, null, null, DEFAULT_NUT_WIDTH, null, null, features);
    }
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,
    float nutWidth, String... features) {
    this(builder, model, backSidesWood, topWood, nutWidth, null, null, features);
    }
    public Guitar(String builder, String model,
    GuitarWood backSidesWood, GuitarWood topWood,
    float nutWidth,
    GuitarInlay fretboardInlay, GuitarInlay topInlay,
    String... features) {
    this.builder = builder;
    this.model = model;
    this.backSidesWood = backSidesWood;
    this.topWood = topWood;
    this.nutWidth = nutWidth;
    this.fretboardInlay = fretboardInlay;
    this.topInlay = topInlay;
    this.features = features;
    }
    }

      你可以簡單地在Java的Collection類中存儲這些可變參數(shù)。

    //變量聲明
    private List features;
    //在方法中或是構(gòu)造器中的書寫
    this.features = java.util.Arrays.asList(features);

      允許零長度的參數(shù)列表

      可變參數(shù)的一個顯著的特性是可變長度參數(shù)可以接受零到N個參數(shù)。這就意味著你可以調(diào)用這些方法中的一個方法而不傳遞任何參數(shù),程序同樣可以運行。從另一方面來說,這又意味著,作為一個程序員,你最好意識到你必須防范這種情況的發(fā)生。

      如何實現(xiàn)它呢?

      記得在“重復(fù)可變長度參數(shù)類表”中,你讀到過下面這個簡單的方法:

    public static int max(int first, int... rest) {
    int max = first;
    for (int i : rest) {
    if (i > max)
    max = i;
    }
    return max;
    }

      你可以以多種形式來調(diào)用這個方法:

    int max = MathUtils.max(1, 4);
    int max = MathUtils.max(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    int max = MathUtils.max(18, 8, 4, 2, 1, 0);

      有一點不是那么令人滿意的地方是,在很多情況下,你要傳遞的數(shù)字已經(jīng)存儲在數(shù)組里,或是至少是在某些集成的形式中:

      //用這種方法來取得數(shù)字

    int[] numbers = getListOfNumbers( );

      要把這些數(shù)字傳遞給max()方法是不可能的。你需要檢查list的長度,從中截取掉第一個對象(如果存在第一個對象的話),然后檢查類型來確 保是int型。完成了這些,你才可以帶著數(shù)組中剩余的部分一起傳遞進入方法。而這數(shù)組中剩余的部分還要重復(fù),或者要人工地轉(zhuǎn)化為適合的格式。總之,這個過 程會很辛苦,你需要做許多瑣碎的事情。仔細(xì)想想,你要記得編譯器是將這個方法解釋為下面的語句:public static int max(int first, int[] rest)

      所以,你可以做些調(diào)整,把max()方法改寫成下面這個樣子:

    public static int max(int... values) {
    int max = Integer.MIN_VALUE;
    for (int i : values) {
    if (i > max)
    max = i;
    }
    return

      你現(xiàn)在已經(jīng)定義了一個可以很容易接受數(shù)組的方法。

    //用這種方法來取得數(shù)字
    int[] numbers = getListOfNumbers( );
    int max = MathUtils.max(numbers);

      當(dāng)接受單一的可變長度參數(shù)時,你使用這種方法會很簡單。但是,如果在最好的情況下,你傳遞了一個零長度的數(shù)組進去,這就會帶來問題,你會得到難 以預(yù)料的結(jié)果。為了解決這個問題,你需要一個小的錯誤檢查。例5-3是MathUtils類的完整代碼列表,在這里是一個功能更強的MathUtil類。

      例5-3 處理零參數(shù)的方法

    package com.oreilly.tiger.ch05;
    public class MathUtils {
    public static int max(int... values) {
    if (values.length == 0) {
    throw new IllegalArgumentException("No values supplied.");
    }

      任何時候,你都可能會要處理零長度的參數(shù)列表,這時你就需要執(zhí)行這類的錯誤檢查。通常,一個功能強大的IllegalArgumentException類是一個好的選擇。

    int max = Integer.MIN_VALUE;
    for (int i : values) {
    if (i > max)
    max = i;
    }
    return max;
    }
    }

      那么關(guān)于調(diào)用同樣的方法來處理通常參數(shù)不是數(shù)組的方法,又會如何呢?這當(dāng)然是完全合法的。下面的代碼都是合法調(diào)用max()方法的手段:

    int max = MathUtils.max(myArray);
    int max = MathUtils.max(new int[] { 2, 4, 6, 8 });
    int max = MathUtils.max(2, 4, 6, 8);
    int max = MathUtils.max(0);
    int max = MathUtils.max( );

      指定對象參數(shù),而非基本類型

      在第四章中我們談到,Tiger通過拆箱增加了一系列的新特征。你可以在處理可變參數(shù)時,在你的方法接受的參數(shù)中使用對象包裝類。

      如何實現(xiàn)?

      你一定記得在Java中所有的類最終都是java.lang.Object的子類。這就意味著任何對象可以被轉(zhuǎn)化成一個Object對象。更進 一步說,因為像int和short這樣的基本類型會自動轉(zhuǎn)化成他們對應(yīng)的對象包裝類(就像Integer和Short),任何Java類型可以被轉(zhuǎn)化成一 個Object對象。

      所以,如果你需要你的可變參數(shù)方法可以接受最多種參數(shù)的類型,那么你可以將Object類型作為參數(shù)的類型。更好的是,為了達到多重功能,絕大多數(shù)情況下都會使用Object對象。例如,寫個用來打印方法。

    private String print(Object... values) {
    StringBuilder sb = new StringBuilder( );
    for (Object o : values) {
    sb.append(o)
    .append(" ");
    }
    return sb.toString( );
    }

      這兒最簡單的意思是打印出所有的東西。然而,這個方法更通用的定義是下面的樣子:

    private String print(String... values) {
    StringBuilder sb = new StringBuilder( );
    for (Object o : values) {
    sb.append(o)
    .append(" ");
    }
    return sb.toString( );
    }

      這個方法的問題是方法自身不能接受字符串,整數(shù),浮點數(shù),數(shù)組和其他的類型數(shù)據(jù),而這些數(shù)據(jù)你都想要正常的打印出來。通過使用Object這個更為通用的類型,你可以來打印所有的一切。

    private String print(Object... values) {
    StringBuilder sb = new StringBuilder( );
    for (Object o : values) {
    sb.append(o)
    .append(" ");
    }
    return sb.toString( );
    }

      避免數(shù)組自動轉(zhuǎn)化

      Tiger增加了各種類型的自動轉(zhuǎn)化和便利,這些東西在絕大多數(shù)的情況下是很好用的。不幸的是,有些時候所有的這些東西會變成你的障礙。其中一 種情況是,在可變參數(shù)方法中將多個Object對象轉(zhuǎn)化為Object[]數(shù)組對象,你會發(fā)現(xiàn)在個別的情況下,你需要用Java來書寫。

      如何實現(xiàn)?

      在將要仔細(xì)討論這件事情前,你要確信自己理解這個問題。Java新的printf()方法是一個很好的便利,舉這個方法作個例子:

    System.out.printf("The balance of %s's account is $%(,6.2f\n",account.getOwner()。getFullName( ),account.getBalance( ));

      如果你看一下Java文檔中關(guān)于printf()方法的說明,你就會看到它是一個可變參數(shù)的方法。它有兩個參數(shù):一個是用于設(shè)置字符串格式的String類型變量,另一個是所有要傳遞進字符串的Object對象:

    PrintStream printf(String format, Object…… args)

      現(xiàn)在,你可以把上面的代碼默認(rèn)為下面的形式:

    PrintStream printf(String format, Object[] args)

      兩種書寫是不是完全相同呢?大多數(shù)情況下是相同的。考慮一下下面的代碼:

    Object[] objectArray = getObjectArrayFromSomewhereElse( );out.printf("Description of object array: %s\n", obj);

      這是乎有點牽強,然而要把它看作是為了自省的代碼而付出的正常開銷。比起其它代碼,這樣寫要簡潔的多。如果你正在編寫一個代碼分析工具,或者一 個集成開發(fā)環(huán)境,或者其他可能使用reflection或簡單API來判斷出應(yīng)用程序會需要何種對象的東西,這些馬上會成為一個通用的案例。這兒,你不是 真正關(guān)心對象數(shù)組的內(nèi)容,就像你同樣不會去關(guān)心數(shù)組自身一樣。它是什么類型?它的內(nèi)存地址是多少?它的字符串代表什么意思?請緊記所有這些問題都是和數(shù)組 本身有關(guān)的,和數(shù)組的內(nèi)容無關(guān)。例如:我們來看看下面的數(shù)組代碼:

    public Object[] getObjectArrayFromSomewhereElse( ) {return new String[] {"Hello", "to", "all", "of", "you"};}

      在這種情況下,你肯能會寫一些像下面一樣的代碼來回答某些關(guān)于數(shù)組的問題:

    out.printf("Description of object array: %s\n", obj);

      然而,輸出結(jié)果并不是你所期望的那樣:

    run-ch05:[echo] Running Chapter 5 examples from Java Tiger: A Developer's Notebook[echo] Running VarargsTester……[java] Hello

      這倒是怎么回事?這就不是你想看到的結(jié)果。然而,編譯器做了它應(yīng)該做的,它把在printf()方法里的Object……轉(zhuǎn)換為 Object[].實際上,當(dāng)編譯器得到你方法的調(diào)用時,它看到的參數(shù)是Object[].所以編譯器不是把這個數(shù)組看作一個Object對象本身,而是 把它分成不同的部分。這樣被傳遞給字符串格式 (%s)的就是第一個參數(shù)部分“Hello”字符串,所以結(jié)果“Hello”就顯示出來了。

      仔細(xì)看看這件事,你需要去告訴編譯器你要把整個對象數(shù)組obj看作是一個簡單的對象,而不是一組參數(shù)。請看下面奇特的代碼:

    out.printf("Description of object array: %s\n", new Object[] { obj });

      作為選擇,還有一種更為簡單的方法:

    out.printf("Description of object array: %s\n", (Object)obj);

      在上面兩種書寫情況下,編譯器不再認(rèn)為是對象的數(shù)組,而是直接認(rèn)為是一個簡單的Object對象,而這個Object對象又恰好是一個對象數(shù)組。那么結(jié)果就如你所愿(至少在這種簡單的應(yīng)用下):

    run-ch05:[echo] Running Chapter 5 examples from Java Tiger: A Developer's Notebook[echo] Running VarargsTester……[java] [Ljava.lang.String;@c44b88

      看到結(jié)果,你肯能會感到有點錯亂。這大概是基于reflection或者其他自省代碼需要的結(jié)果。

    posted on 2008-08-07 18:12 gembin 閱讀(355) 評論(0)  編輯  收藏 所屬分類: JavaSE

    導(dǎo)航

    統(tǒng)計

    常用鏈接

    留言簿(6)

    隨筆分類(440)

    隨筆檔案(378)

    文章檔案(6)

    新聞檔案(1)

    相冊

    收藏夾(9)

    Adobe

    Android

    AS3

    Blog-Links

    Build

    Design Pattern

    Eclipse

    Favorite Links

    Flickr

    Game Dev

    HBase

    Identity Management

    IT resources

    JEE

    Language

    OpenID

    OSGi

    SOA

    Version Control

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    free counters
    主站蜘蛛池模板: 中文在线日本免费永久18近| 五月婷婷免费视频| 全部免费a级毛片| 四虎永久在线精品免费观看地址| 免费人成网站7777视频| 国产亚洲成人在线播放va| 亚洲阿v天堂在线2017免费| 亚洲国产日韩在线视频| 亚洲日韩乱码中文无码蜜桃| 亚洲人成自拍网站在线观看| www成人免费视频| 精品熟女少妇av免费久久| 啦啦啦www免费视频| 自拍偷自拍亚洲精品第1页| 亚洲AV无码乱码在线观看| 久久被窝电影亚洲爽爽爽| 亚洲精品无码MV在线观看| 亚洲性猛交xx乱| 日本精品久久久久久久久免费| 免费毛片毛片网址| 一级毛片免费毛片一级毛片免费| 暖暖在线视频免费视频| 午夜视频免费在线观看| 成人毛片18女人毛片免费96| 美腿丝袜亚洲综合| 77777午夜亚洲| 中国精品一级毛片免费播放| 一二三四影视在线看片免费| 国产精品亚洲产品一区二区三区| 亚洲天堂一区在线| 一区二区三区免费在线观看| 美女内射毛片在线看免费人动物| 免费一看一级毛片全播放| 亚洲高清日韩精品第一区| 日韩毛片一区视频免费| 99久久99久久精品免费看蜜桃| 国产a v无码专区亚洲av| 亚洲男人天堂2018av| 在线观看片免费人成视频无码| 日本免费中文字幕在线看| 亚洲天堂男人天堂|