欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java中"Test(Object...args){}"方法聲明的理解——J2SE5的“V...
J2SE 1.5提供了“Varargs”機制。借助這一機制,可以定義能和多個(gè)實(shí)參相匹配的形參。從而,可以用一種更簡(jiǎn)單的方式,來(lái)傳遞個(gè)數可變的實(shí)參。本文介紹這一機制的使用方法,以及這一機制與數組、泛型、重載之間的相互作用時(shí)的若干問(wèn)題。
到J2SE 1.4為止,一直無(wú)法在Java程序里定義實(shí)參個(gè)數可變的方法——因為Java要求實(shí)參(Arguments)和形參(Parameters)的數量和類(lèi) 型都必須逐一匹配,而形參的數目是在定義方法時(shí)就已經(jīng)固定下來(lái)了。盡管可以通過(guò)重載機制,為同一個(gè)方法提供帶有不同數量的形參的版本,但是這仍然不能達到 讓實(shí)參數量任意變化的目的。
然而,有些方法的語(yǔ)義要求它們必須能接受個(gè)數可變的實(shí)參——例如著(zhù)名的main方法,就需要能接受所有的命令行參數為實(shí)參,而命令行參數的數目,事先根本無(wú)法確定下來(lái)。
對于這個(gè)問(wèn)題,傳統上一般是采用“利用一個(gè)數組來(lái)包裹要傳遞的實(shí)參”的做法來(lái)應付。
1. 用數組包裹實(shí)參
“用數組包裹實(shí)參”的做法可以分成三步:首先,為這個(gè)方法定義一個(gè)數組型的參數;然后在調用時(shí),生成一個(gè)包含了所有要傳遞的實(shí)參的數組;最后,把這個(gè)數組作為一個(gè)實(shí)參傳遞過(guò)去。
這種做法可以有效的達到“讓方法可以接受個(gè)數可變的參數”的目的,只是調用時(shí)的形式不夠簡(jiǎn)單。
J2SE 1.5中提供了Varargs機制,允許直接定義能和多個(gè)實(shí)參相匹配的形參。從而,可以用一種更簡(jiǎn)單的方式,來(lái)傳遞個(gè)數可變的實(shí)參。
Varargs的含義
大體說(shuō)來(lái),“Varargs”是“variable number of arguments”的意思。有時(shí)候也被簡(jiǎn)單的稱(chēng)為“variable arguments”,不過(guò)因為這一種叫法沒(méi)有說(shuō)明是什么東西可變,所以意義稍微有點(diǎn)模糊。
2. 定義實(shí)參個(gè)數可變的方法
只要在一個(gè)形參的“類(lèi)型”與“參數名”之間加上三個(gè)連續的“.”(即“...”,英文里的句中省略號),就可以讓它和不確定個(gè)實(shí)參相匹配。而一個(gè)帶有這樣的形參的方法,就是一個(gè)實(shí)參個(gè)數可變的方法。
清單1:一個(gè)實(shí)參個(gè)數可變的方法
Java代碼
private static int sumUp(int... values) {    
}   
private static int sumUp(int... values) {
} 注意,只有最后一個(gè)形參才能被定義成“能和不確定個(gè)實(shí)參相匹配”的。因此,一個(gè)方法里只能有一個(gè)這樣的形參。另外,如果這個(gè)方法還有其它的形參,要把它們放到前面的位置上。
編譯器會(huì )在背地里把這最后一個(gè)形參轉化為一個(gè)數組形參,并在編譯出的class文件里作上一個(gè)記號,表明這是個(gè)實(shí)參個(gè)數可變的方法。
清單2:實(shí)參個(gè)數可變的方法的秘密形態(tài)
Java代碼
private static int sumUp(int[] values) {    
}   
private static int sumUp(int[] values) {
} 由于存在著(zhù)這樣的轉化,所以不能再為這個(gè)類(lèi)定義一個(gè)和轉化后的方法簽名一致的方法。
清單3:會(huì )導致編譯錯誤的組合
Java代碼
private static int sumUp(int... values) {   
}   
  
private static int sumUp(int[] values) {   
}  
    private static int sumUp(int... values) {
    }
    private static int sumUp(int[] values) {
    }
空白的存亡問(wèn)題
根據J2SE 1.5的語(yǔ)法,在“...”前面的空白字符是可有可無(wú)的。這樣就有在“...”前面添加空白字符(形如“Object ... args”)和在“...”前面不加空白字符(形如“Object... args”)的兩種寫(xiě)法。因為目前和J2SE 1.5相配合的Java Code Conventions還沒(méi)有正式發(fā)布,所以無(wú)法知道究竟哪一種寫(xiě)法比較正統。不過(guò),考慮到數組參數也有“Object [] args”和“Object[] args”兩種書(shū)寫(xiě)方式,而正統的寫(xiě)法是不在“[]”前添加空白字符,似乎采取不加空白的“Object... args”的寫(xiě)法在整體上更協(xié)調一些。
3. 調用實(shí)參個(gè)數可變的方法
只要把要傳遞的實(shí)參逐一寫(xiě)到相應的位置上,就可以調用一個(gè)實(shí)參個(gè)數可變的方法。不需要其它的步驟。
清單4:可以傳遞若干個(gè)實(shí)參
sumUp(1, 3, 5, 7);
在背地里,編譯器會(huì )把這種調用過(guò)程轉化為用“數組包裹實(shí)參”的形式:
清單5:偷偷出現的數組創(chuàng )建
sumUp(new int[]{1, 2, 3, 4});
另外,這里說(shuō)的“不確定個(gè)”也包括零個(gè),所以這樣的調用也是合乎情理的:
清單6:也可以傳遞零個(gè)實(shí)參
sumUp();
這種調用方法被編譯器秘密轉化之后的效果,則等同于這樣:
清單7:零實(shí)參對應空數組
sumUp(new int[]{});
注意這時(shí)傳遞過(guò)去的是一個(gè)空數組,而不是null。這樣就可以采取統一的形式來(lái)處理,而不必檢測到底屬于哪種情況。
4. 處理個(gè)數可變的實(shí)參
處理個(gè)數可變的實(shí)參的辦法,和處理數組實(shí)參的辦法基本相同。所有的實(shí)參,都被保存到一個(gè)和形參同名的數組里。根據實(shí)際的需要,把這個(gè)數組里的元素讀出之后,要蒸要煮,就可以隨意了。
清單8:處理收到的實(shí)參們
Java代碼
private static int sumUp(int... values) {   
    int sum = 0;   
    for (int i = 0; i < values.length; i++) {   
        sum += values[i];   
    }   
    return sum;   
}  
    private static int sumUp(int... values) {
        int sum = 0;
        for (int i = 0; i < values.length; i++) {
            sum += values[i];
        }
        return sum;
    }
5. 轉發(fā)個(gè)數可變的實(shí)參
有時(shí)候,在接受了一組個(gè)數可變的實(shí)參之后,還要把它們傳遞給另一個(gè)實(shí)參個(gè)數可變的方法。因為編碼時(shí)無(wú)法知道接受來(lái)的這一組實(shí)參的數目,所以“把它們 逐一寫(xiě)到該出現的位置上去”的做法并不可行。不過(guò),這并不意味著(zhù)這是個(gè)不可完成的任務(wù),因為還有另外一種辦法,可以用來(lái)調用實(shí)參個(gè)數可變的方法。
在J2SE 1.5的編譯器的眼中,實(shí)參個(gè)數可變的方法是最后帶了一個(gè)數組形參的方法的特例。因此,事先把整組要傳遞的實(shí)參放到一個(gè)數組里,然后把這個(gè)數組作為最后一個(gè)實(shí)參,傳遞給一個(gè)實(shí)參個(gè)數可變的方法,不會(huì )造成任何錯誤。借助這一特性,就可以順利的完成轉發(fā)了。
清單9:轉發(fā)收到的實(shí)參們
Java代碼
public class PrintfSample {   
  
    public static void main(String[] args) {   
        // 打印出“Pi:3.141593 E:2.718282”   
        printOut("Pi:%f E:%f\n", Math.PI, Math.E);   
    }   
  
    private static void printOut(String format, Object... args) {   
        // J2SE 1.5里PrintStream新增的printf(String format, Object... args)方法   
        System.out.printf(format, args);   
    }   
}  
    public class PrintfSample {
        public static void main(String[] args) {
            // 打印出“Pi:3.141593 E:2.718282”
            printOut("Pi:%f E:%f\n", Math.PI, Math.E);
        }
        private static void printOut(String format, Object... args) {
            // J2SE 1.5里PrintStream新增的printf(String format, Object... args)方法
            System.out.printf(format, args);
        }
    }
Java里的“printf”和“sprintf”
C語(yǔ)言里的printf(按一定的格式輸出字符串)和sprintf(按一定的格式組合字符串)是十分經(jīng)典的使用Varargs機制的例子。在 J2SE 1.5中,也分別在java.io.PrintStream類(lèi)和java.lang.String類(lèi)中提供了類(lèi)似的功能。
按一定的格式輸出字符串的功能,可以通過(guò)調用PrintStream對象的printf(String format, Object... args)方法來(lái)實(shí)現。
按一定的格式組合字符串的工作,則可以通過(guò)調用String類(lèi)的String format(String format, Object... args)靜態(tài)方法來(lái)進(jìn)行。
6. 是數組?不是數組?
盡管在背地里,編譯器會(huì )把能匹配不確定個(gè)實(shí)參的形參,轉化為數組形參;而且也可以用數組包了實(shí)參,再傳遞給實(shí)參個(gè)數可變的方法;但是,這并不表示“能匹配不確定個(gè)實(shí)參的形參”和“數組形參”完全沒(méi)有差異。
一個(gè)明顯的差異是,如果按照調用實(shí)參個(gè)數可變的方法的形式,來(lái)調用一個(gè)最后一個(gè)形參是數組形參的方法,只會(huì )導致一個(gè)“cannot be applied to”的編譯錯誤。
清單10:一個(gè)“cannot be applied to”的編譯錯誤
Java代碼
private static void testOverloading(int[] i) {   
    System.out.println("A");   
}   
  
public static void main(String[] args) {   
    testOverloading(1, 2, 3);// 編譯出錯   
}  
    private static void testOverloading(int[] i) {
        System.out.println("A");
    }
    public static void main(String[] args) {
        testOverloading(1, 2, 3);// 編譯出錯
    }
由于這一原因,不能在調用只支持用數組包裹實(shí)參的方法的時(shí)候(例如在不是專(zhuān)門(mén)為J2SE 1.5設計第三方類(lèi)庫中遺留的那些),直接采用這種簡(jiǎn)明的調用方式。
如果不能修改原來(lái)的類(lèi),為要調用的方法增加參數個(gè)數可變的版本,而又想采用這種簡(jiǎn)明的調用方式,那么可以借助“引入外加函數(Introduce Foreign Method)”和“引入本地擴展(Intoduce Local Extension)”的重構手法來(lái)近似的達到目的。
7. 當個(gè)數可變的實(shí)參遇到泛型
J2SE 1.5中新增了“泛型”的機制,可以在一定條件下把一個(gè)類(lèi)型參數化。例如,可以在編寫(xiě)一個(gè)類(lèi)的時(shí)候,把一個(gè)方法的形參的類(lèi)型用一個(gè)標識符(如T)來(lái)代表, 至于這個(gè)標識符到底表示什么類(lèi)型,則在生成這個(gè)類(lèi)的實(shí)例的時(shí)候再行指定。這一機制可以用來(lái)提供更充分的代碼重用和更嚴格的編譯時(shí)類(lèi)型檢查。
不過(guò)泛型機制卻不能和個(gè)數可變的形參配合使用。如果把一個(gè)能和不確定個(gè)實(shí)參相匹配的形參的類(lèi)型,用一個(gè)標識符來(lái)代表,那么編譯器會(huì )給出一個(gè)“generic array creation”的錯誤。
清單11:當Varargs遇上泛型
Java代碼
private static <T> void testVarargs(T... args) {   
    // 編譯出錯   
}  
    private static <T> void testVarargs(T... args) {
        // 編譯出錯
    }
造成這個(gè)現象的原因在于J2SE 1.5中的泛型機制的一個(gè)內在約束——不能拿用標識符來(lái)代表的類(lèi)型來(lái)創(chuàng )建這一類(lèi)型的實(shí)例。在出現支持沒(méi)有了這個(gè)約束的Java版本之前,對于這個(gè)問(wèn)題,基本沒(méi)有太好的解決辦法。
不過(guò),傳統的“用數組包裹”的做法,并不受這個(gè)約束的限制。
清單12:可以編譯的變通做法
Java代碼
private static <T> void testVarargs(T[] args) {   
    for (int i = 0; i < args.length; i++) {   
        System.out.println(args[i]);   
    }   
}  
    private static <T> void testVarargs(T[] args) {
        for (int i = 0; i < args.length; i++) {
            System.out.println(args[i]);
        }
    }
8. 重載中的選擇問(wèn)題
Java支持“重載”的機制,允許在同一個(gè)類(lèi)擁有許多只有形參列表不同的方法。然后,由編譯器根據調用時(shí)的實(shí)參來(lái)選擇到底要執行哪一個(gè)方法。
傳統上的選擇,基本是依照“特殊者優(yōu)先”的原則來(lái)進(jìn)行。一個(gè)方法的特殊程度,取決于為了讓它順利運行而需要滿(mǎn)足的條件的數目,需要條件越多的越特殊。
在引入Varargs機制之后,這一原則仍然適用,只是要考慮的問(wèn)題豐富了一些——傳統上,一個(gè)重載方法的各個(gè)版本之中,只有形參數量與實(shí)參數量正 好一致的那些有被進(jìn)一步考慮的資格。但是Varargs機制引入之后,完全可以出現兩個(gè)版本都能匹配,在其它方面也別無(wú)二致,只是一個(gè)實(shí)參個(gè)數固定,而一 個(gè)實(shí)參個(gè)數可變的情況。
遇到這種情況時(shí),所用的判定規則是“實(shí)參個(gè)數固定的版本優(yōu)先于實(shí)參個(gè)數可變的版本”。
清單13:實(shí)參個(gè)數固定的版本優(yōu)先
Java代碼
public class OverloadingSampleA {   
  
    public static void main(String[] args) {   
        testOverloading(1);// 打印出A   
        testOverloading(1, 2);// 打印出B   
        testOverloading(1, 2, 3);// 打印出C   
    }   
  
    private static void testOverloading(int i) {   
        System.out.println("A");   
    }   
  
    private static void testOverloading(int i, int j) {   
        System.out.println("B");   
    }   
  
    private static void testOverloading(int i, int... more) {   
        System.out.println("C");   
    }   
}  
public class OverloadingSampleA {
    public static void main(String[] args) {
        testOverloading(1);// 打印出A
        testOverloading(1, 2);// 打印出B
        testOverloading(1, 2, 3);// 打印出C
    }
    private static void testOverloading(int i) {
        System.out.println("A");
    }
    private static void testOverloading(int i, int j) {
        System.out.println("B");
    }
    private static void testOverloading(int i, int... more) {
        System.out.println("C");
    }
}
如果在編譯器看來(lái),同時(shí)有多個(gè)方法具有相同的優(yōu)先權,它就會(huì )陷入無(wú)法就到底調用哪個(gè)方法作出一個(gè)選擇的狀態(tài)。在這樣的時(shí)候,它就會(huì )產(chǎn)生一個(gè) “reference to 被調用的方法名 is ambiguous”的編譯錯誤,并耐心的等候作了一些修改,足以免除它的迷惑的新源代碼的到來(lái)。
在引入了Varargs機制之后,這種可能導致迷惑的情況,又增加了一些。例如現在可能會(huì )有兩個(gè)版本都能匹配,在其它方面也如出一轍,而且都是實(shí)參個(gè)數可變的沖突發(fā)生。
清單14:左右都不是,為難了編譯器
Java代碼
public class OverloadingSampleB {   
  
    public static void main(String[] args) {   
        testOverloading(1, 2, 3);// 編譯出錯   
    }   
  
    private static void testOverloading(Object... args) {   
    }   
  
    private static void testOverloading(Object o, Object... args) {   
    }   
}  
public class OverloadingSampleB {
    public static void main(String[] args) {
        testOverloading(1, 2, 3);// 編譯出錯
    }
    private static void testOverloading(Object... args) {
    }
    private static void testOverloading(Object o, Object... args) {
    }
}
另外,因為J2SE 1.5中有“Autoboxing/Auto-Unboxing”機制的存在,所以還可能發(fā)生兩個(gè)版本都能匹配,而且都是實(shí)參個(gè)數可變,其它方面也一模一樣,只是一個(gè)能接受的實(shí)參是基本類(lèi)型,而另一個(gè)能接受的實(shí)參是包裹類(lèi)的沖突發(fā)生。
清單15:Autoboxing/Auto-Unboxing帶來(lái)的新問(wèn)題
Java代碼
public class OverloadingSampleC {   
  
    public static void main(String[] args) { /* 編譯出錯 */  
        testOverloading(1, 2); /* 還是編譯出錯 */  
        testOverloading(new Integer(1), new Integer(2));   
    }   
  
    private static void testOverloading(int... args) {   
    }   
  
    private static void testOverloading(Integer... args) {   
    }   
}  
public class OverloadingSampleC {
    public static void main(String[] args) { /* 編譯出錯 */
        testOverloading(1, 2); /* 還是編譯出錯 */
        testOverloading(new Integer(1), new Integer(2));
    }
    private static void testOverloading(int... args) {
    }
    private static void testOverloading(Integer... args) {
    }
}
9. 歸納總結
和“用數組包裹”的做法相比,真正的實(shí)參個(gè)數可變的方法,在調用時(shí)傳遞參數的操作更為簡(jiǎn)單,含義也更為清楚。不過(guò),這一機制也有它自身的局限,并不是一個(gè)完美無(wú)缺的解決方案。
參考資源
可以通過(guò)Sun的Java Technology頁(yè)面找到下載J2SE 1.5的SDK及其文檔的鏈接,目前的最新版本是J2SDK 5.0 Beta 2。 《JSR 201: Extending the Java Programming Language with Enumerations, Autoboxing, Enhanced for loops and Static Import》中定義了很多在J2SE 1.5中出現了的新語(yǔ)言特性。雖然在標題里并沒(méi)有明確提到,但是Varargs機制也在其中。 Calvin Austin在《J2SE 1.5 in a Nutshell》一文中,比較全面的對J2SE 1.5的新特性進(jìn)行了簡(jiǎn)單的介紹。 John Zukowski在《馴服 Tiger:Tiger 預覽版現已推出》一文中,介紹了如何開(kāi)始使用J2SDK 1.5的基礎知識。不過(guò)因為這篇文章是依照J2SDK 1.5 Alpha版的狀況所寫(xiě),所以里面提到的一些細節(如下載地址和默認安裝路徑)已經(jīng)發(fā)生了變化。 John Zukowski在《馴服 Tiger:格式化輸出》一文中,介紹了利用J2SE 1.5中新增的功能進(jìn)行字符串格式化的辦法。 Gilad Bracha在《Generics in the Java Programming Language》一文中,細致的介紹了J2SE 1.5中的泛型機制的使用方法和各種限制。 Martin Fowler在《Refactoring -- Improving the Design of Existing Code》(中譯本名為《重構——改善既有代碼的設計》, 由侯捷、熊節合譯)一書(shū)的第七章《在對象之間移動(dòng)特性(Moving Features Between Objects)》中,介紹了被稱(chēng)作“引入外加函數(Introduce Foreign Method)”和“引入本地擴展(Intoduce Local Extension)”的重構手法。 Gilad Bracha、James Gosling、Bill Joy和Guy Steele在《The Java Language Specification, 2nd Edition》一書(shū)里的《Classes》一章中的《Overloading》一節和《Expression》一章中的《Method Invocation Expressions》一節里深入的討論了重載方面的問(wèn)題。不過(guò)因為這本書(shū)是依照J2SDK 1.2版的狀況所寫(xiě),所以并沒(méi)有完整地涵蓋J2SE 1.5中的實(shí)際情況。

本文來(lái)自CSDN博客,轉載請標明出處:http://blog.csdn.net/wfy1987/archive/2009/03/16/3993468.aspx
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java中不定項參數(可變參數)的作用和使用方式
V6.5引用傳遞 ref/out/params
java學(xué)習筆記 方法篇01
JAVA基礎編程練習題
第五天 方法【悟空教程】
數組的遍歷方法
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久