日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java語(yǔ)言基礎(chǔ)特性—第一部分(下)

 yxhuang 2014-05-16

你可以通過(guò)指定extends后接類型名稱來(lái)提供通配符的上界。同樣的,你可以通過(guò)指定super后接類型名稱來(lái)提供通配符的下界。這些限定限制了可以作為實(shí)際類型參數(shù)傳入的類型。

在例子中,你可以把? extends String理解為任何String或其子類的實(shí)際類型參數(shù)。同樣的,你可以把? super String理解為任何String或其父類的實(shí)際類型參數(shù)。因?yàn)镾tring是final的,這意味著它不能被繼承,只有源列表為String對(duì)象,目標(biāo)列表為String或Object對(duì)象能夠傳入作為參數(shù),這樣用處不大。

你可以使用泛型方法來(lái)完全解決這個(gè)問(wèn)題,它是一個(gè)有類型實(shí)現(xiàn)參數(shù)的類或接口方法。泛型方法支持下面的語(yǔ)法:

1
2
<formalTypeParameterList> returnType
identifier(parameterList)

泛型方法的形參列表在它的返回類型之前。它包含類型參數(shù)和可選的上界。類型參數(shù)可以作為返回類型使用,并且可以出現(xiàn)在參數(shù)列表中。

清單9展示了怎么定義和調(diào)用泛型copy()方法

Listing 9. GenDemo.java (version 5)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.util.ArrayList;
import java.util.List;
 
public class GenDemo
{
   public static void main(String[] args)
   {
      List<Integer> grades = new ArrayList<Integer>();
      Integer[] gradeValues =
      {
         new Integer(96),
         new Integer(95),
         new Integer(27),
         new Integer(100),
         new Integer(43),
         new Integer(68)
      };
      for (int i = 0; i < gradeValues.length; i++)
         grades.add(gradeValues[i]);
      List<Integer> failedGrades = new ArrayList<Integer>();
      copy(grades, failedGrades, new Filter<Integer>()
                                 {
                                    public boolean accept(Integer grade)
                                    {
                                       return grade.intValue() <= 50;
                                    }
                                 });
      for (int i = 0; i < failedGrades.size(); i++)
         System.out.println(failedGrades.get(i));
   }
 
   static <T> void copy(List<T> src, List<T> dest,
Filter<T> filter)
   {
      for (int i = 0; i < src.size(); i++)
         if (filter.accept(src.get(i)))
            dest.add(src.get(i));
   }
}
 
interface Filter<T>
{
   boolean accept(T o);
}

清單9中我定義了一個(gè)<T> void copy(List<T> src, List<T> dest, Filter<T> filter)泛型方法。編譯器注意到srcdestfilter參數(shù)的類型都包含類型參數(shù)T。這意味著在方法調(diào)用中必須傳入同樣的實(shí)際類型參數(shù),而編譯器會(huì)在調(diào)用中獲取參數(shù)。

如果你編譯清單9(javac GenDemo.java)并運(yùn)行程序(java GenDemo),你應(yīng)該可以看到下面的輸出:

1
2
27
43

Java語(yǔ)言中關(guān)于泛型最有爭(zhēng)議的是什么?

雖然泛型本身并不具爭(zhēng)議,但它在Java語(yǔ)言中的特殊實(shí)現(xiàn)卻是。泛型是作為消除轉(zhuǎn)換的語(yǔ)法糖的編譯時(shí)特性來(lái)實(shí)現(xiàn)的。編譯器會(huì)在編譯源碼后丟棄泛型類型或泛型的形參類型列表。這個(gè)“丟棄”行為稱為擦除(erasure)。其他在泛型中關(guān)于擦除的例子包含:在代碼類型不正確時(shí),插入時(shí)可以自動(dòng)轉(zhuǎn)換為合適的類型;通過(guò)上界(例如Object)來(lái)替換類型參數(shù)。

更多關(guān)于泛型的討論

泛型不只因?yàn)椴脸鴤涫軤?zhēng)議??匆幌耂tackOverflow.com的“為什么我們抱怨Java關(guān)于泛型的實(shí)現(xiàn)很糟糕”主題的討論,包含了通配符很難理解和事實(shí)上泛型并不直接值類型(例如,你不能指定List<int>)。

使用擦除會(huì)有下面的幾個(gè)限制:

  • instanceof并不能用于參數(shù)化類型,只有一種情況是例外的。這個(gè)例外就是無(wú)界的通配符。例如,你不能指定Set<Shape> shapes = null; if (shapes instanceof ArrayList<Shape>){}。相反,你需要把對(duì)instanceof表達(dá)式修改為shapes instanceof ArrayList<?>,這種就是無(wú)界的通配符?;蛘撸憧梢灾付?code>shapes instanceof ArrayList,這使用的是原生類型(通常也是推薦使用的做法)。

  • 編譯器把泛型代碼轉(zhuǎn)換為非泛型代碼,并保存在class文件中。一些開(kāi)發(fā)人員指出擦除會(huì)使得你不能通過(guò)反射取得泛型信息,因?yàn)樗鼈儾⒉槐4嬖赾lass文件中。開(kāi)發(fā)人員Jakob Jenkov在“Java 反射:泛型”中指出一些泛型信息會(huì)被保存在class文件中的情況,并且這些信息可以通過(guò)反射來(lái)訪問(wèn)。

  • 你不能在創(chuàng)建數(shù)組的表達(dá)式中使用類型參數(shù);例如,elements = new E[size];。如果你這樣做,編譯器會(huì)報(bào)告泛型數(shù)組創(chuàng)建錯(cuò)誤信息。

鑒于擦除的限制,你會(huì)奇怪為什么泛型要通過(guò)擦除來(lái)實(shí)現(xiàn)。原因很簡(jiǎn)單:Java編譯器被重構(gòu)來(lái)使用擦除,因此泛型代碼可以跟那些非泛型的遺留代碼進(jìn)行交互。沒(méi)有這個(gè)向后兼容性,遺留代碼在支持泛型的Java編譯器上編譯時(shí)將會(huì)報(bào)錯(cuò)。

第一部分總結(jié)

Java語(yǔ)言已經(jīng)添加了許多新特性。在這篇文章中,我展示了怎么使用斷言來(lái)增強(qiáng)你在代碼正確性上的信心,和如何使用泛型來(lái)消除ClassCastException。通過(guò)使用斷言和泛型,你可以編寫(xiě)更可靠的代碼,并且使你的代碼在運(yùn)行時(shí)的錯(cuò)誤降到最低,當(dāng)然,也減少面對(duì)生氣的客戶時(shí)的頭痛了。

Java 5 是Java平臺(tái)歷史上的一個(gè)重大發(fā)布,雖然泛型比其他特性都更具爭(zhēng)議,但它卻比其他都更加重要。我的下篇文章將會(huì)介紹另外7個(gè)在Java5時(shí)加入的必要的特性:類型安全的枚舉,注解,自動(dòng)裝箱和拆箱,加強(qiáng)的循環(huán),靜態(tài)引入,可變參數(shù),協(xié)變返回類型。在那之前,下載這篇文章的源代碼,它包含了更多的關(guān)于斷言和泛型的提示和例子。

Jeff Friesen是一個(gè)自由職業(yè)導(dǎo)師和側(cè)重Java和Android的軟件開(kāi)發(fā)人員。除了為Apress寫(xiě)Java和Android書(shū)籍,Jeff為JavaWorld,informITJava.net,DevSourceSitePoint寫(xiě)了大量的關(guān)于Java和其他技術(shù)的文章。你可以通過(guò)他在TutorTutor.ca的網(wǎng)站聯(lián)系到他

了解更多主題相關(guān)

下載文章的源代碼
閱讀Angelika Langer的Java Generics FAQs,那里有著大量的關(guān)于Java語(yǔ)言泛型的信息和觀點(diǎn)。

對(duì)于想學(xué)習(xí)Java語(yǔ)言和它的備受爭(zhēng)議的特性的,Langer的文章理解閉包的爭(zhēng)論(2008.6 JavaWorld)對(duì)比了Java 7語(yǔ)言中的三個(gè)關(guān)于添加閉包和lambda表達(dá)式的初始提議。

可以查看“Java反射:泛型”(Jakob Jenkov, Jenkov.com)關(guān)于泛型反射和某些情況下可以在運(yùn)行時(shí)獲取泛型信息的討論。
Java無(wú)痛并發(fā)編程,第一部(2013.6):介紹了Executor框架,同步類型和Java并發(fā)集合包。

Java無(wú)痛并發(fā)編程,第二部(2013.8):介紹了鎖,原子變量和fork/join操作,還附加了Java8中關(guān)于java.util.concurrent的修改概述。
跟上Java Date和Time API(2013.4):介紹了Java8的JSR310:Date 和Time API,并且展示了你最有可能使用的java.time系列類的使用。
JavaWorld中更多關(guān)于Java集合框架的文章:
Java集合框架從零開(kāi)始(1998.11 Dan Becker):這篇文章介紹了集合剛引入java時(shí)的歷史。
Java集合中的省時(shí)習(xí)慣(2013.9 Java Q&A blog):展望未來(lái),Jeff Friesen回答一些當(dāng)前使用Java集合的常見(jiàn)問(wèn)題。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多