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

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

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

    Vincent

    Vicent's blog
    隨筆 - 74, 文章 - 0, 評論 - 5, 引用 - 0
    數據加載中……

    generic-泛型/類屬

    管中窺虎

    在學習 java 1.5 的過程中,我使用了 sun 公布的 tutorial ,這份文檔寫的比較詳盡易明,但是對于想快速了解 tiger 而且具有較好 java 基礎的人來說,大篇幅的英文文檔是比較耗時間和非必需的,所以我將會歸納這份文檔的主要內容,在保證理解的底線上,盡力減少閱讀者需要的時間。

    ?

    在以下地址可以進入各新增語言特色介紹以及下載相關文檔(若有)。

    http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html

    ?

    第一道虎紋: generic -泛型 / 類屬

    什么是泛型

    泛型讓你在類這一層次上進行抽象。看看例子:

    List?myIntList? = ? new ?LinkedList();? // ?1?

    myIntList.add(
    new ?Integer( 0 ));? // ?2?

    Integer?x?
    = ?(Integer)?myIntList.iterator().next();? // ?3?

    ?

    ?

    3 句的轉換類型有點麻煩吧~?編譯器只能保證容器類里放的是 Object 對象,要使用他們只能這樣去轉換。而且這樣的轉換也并不是完全安全的,程序員可能犯錯誤,容器里的對象未必是他以為的對象。有沒有辦法顯式地表達出程序員的意圖,將該容器限制為只能保存特定類型的對象?這正是 generic -泛型的核心用意。

    ?

    ?

    List? < ?Integer? > ?myIntList? = ? new ?LinkedList? < ?Integer? > ?();? // ?1’?

    myIntList.add(
    new ?Integer( 0 ));? // 2’?

    Integer?x?
    = ?myIntList.iterator().next();? // ?3’?

    ?

    ?

    這樣子我們就聲明了一個只放 Integer List ,我們說 List 是一個 generic Interface ,接收了一個類型參數,在上例中就是 Integer 。在初始化的時候,同樣的也指定了這個類型參數。

    要注意這些工作的效果不是僅僅把原來的第 3 句的轉換工作省掉,而是由此讓編譯器確保了這個 List 在程序的任何位置任何時候都用以存放正確的類型,而原來的類型轉換僅僅告訴我們在這一單點處程序員自己認為的類型。

    泛型由此為程序,尤其是大型程序,帶來了可讀性和健壯性。

    定義簡單的泛型

    ?

    ?public?interface?List?<?E?>?{?

    ???????void?add(E?x);?

    ??????Iterator?
    <?E?>?iterator();?

    }
    ?public?interface?Iterator?<?E?>?{?

    ?????????E?next();?

    ?????????boolean?hasNext();?

    }
    ?

    尖括號內的標識符就是一個類型形式參數。類似于方法的參數,當你使用的時候就替換一個實際參數進去,只不過這個參數是個類型。在上面的例子中,我們就替換了一個

    Integer 類型進去。

    在這里稍微說一下命名的規范,定義泛型中的形式參數時,使用簡潔有力又具有啟發性的名字,如果可以的話用單個字母更好。避免使用小寫,以免和普通的方法參數混淆。

    ?

    泛型與子類

    ?

    看看以下的例子語句合法嗎?

    ?

    List? < ?String? > ?ls? = ? new ?ArrayList? < ?String? > ?();? // 1?

    List?
    < ?Object? > ?lo? = ?ls;? // 2?

    ?

    2 句是行不通的,看看以下的語句:

    lo.add( new ?Object());? // ?3?

    String?s?
    = ?ls.get( 0 );? // ?4:?試圖將?Object?對象賦值給字符串對象,編譯錯誤?

    簡而言之就是,原有類型的繼承關系是不會反映到對應的泛型上來,在上述情況下,任何兩個泛型類型都不存在繼承關系。那么,習慣了面向接口編程的我們怎樣去適應這種嚴格的使用限制呢?

    ?

    通配符

    假如我們要用一個方法把一個容器內的元素都 print 出來,可以用這樣的代碼來實現 :

    void ?printCollection(Collection?c)? {?

    ?????????Iterator?i?
    = ?c.iterator();?

    ????for?(k?=?0;?k?<?c.size();?k++)?{?

    ?????????System.out.println(i.next());?

    ??????}

    ?????}
    ?

    如果我們用新的泛型和新的

    for 語句(你可以先不了解它,以后會談到)來嘗試同樣的功能,以下代碼可行嗎?

    ??void?printCollection(Collection?<?Object?>?c)?{?

    ??
    ????for?(Object?e?:?c)?{?

    ???????????System.out.println(e);?

    ?????????}

    }

    ?

    事實是,新的代碼的使用范圍非常有限,因為 Collection < Object > 就只是一個放 Object 的容器泛類,它不是 任何其他 Collection 泛類的父類!真正擔任這個角色的是:

    Collection < ? >

    這個問號代表了未知, Collection < ? > 的元素可以是任何類型,這就是通配類型。

    現在我們可以這樣寫:

    void ?printCollection(Collection? < ? ? ? > ?c)? {?

    ??
    for ?(Object?e?:?c)? {?

    ?????????System.out.println(e);?

    ??????}
    ?
    }
    ?

    ?

    注意在循環里面,可以把元素賦值給一個 Object 類型,因為無論 c 里放的是什么,它肯定是一個 Object ,但向 c 里放置對象則是不安全的,因為不知道 c 的泛型是什么。如下面這樣是不行的:

    Collection? < ? ? ? > ?c? = ? new ?ArrayList? < ?String? > ?();?

    c.add(
    new ?Object());? // ?編譯錯誤?

    ?

    add() 方面接納的是泛型的形式參數里描述的類型(或它的子類,希望你對此不感到混亂,呵呵。),然而此時我們只看到一個問號,我們不知道它的類型參數是什么,當然就不能放置對象進去。唯一一個例外是 null ,它是任何一個類型的對象集的一分子。

    ?

    受限通配符

    省去一些說明性的代碼,以我們熟悉的幾何圖形家族例子來說明:

    ?

    public ? void ?drawAll(List? < ? ? ? extends ?Shape? > ?shapes)? {??} ?

    ?

    一個 List<T> ,如果 T Shape 的子類,那么這個 List 都可以被上面這個方法接納為參數,這個就是受限的通配符。 Shape 就稱為這個通配符的上限。

    看看下面的代碼,怎樣?

    public ? void ?addRectangle(List? < ? ? ? extends ?Shape? > ?shapes)? {?

    ??????shapes.add(
    0 ,? new ?Rectangle());? // ?compile-time?error!?

    }
    ?

    如上的方法依然是不行的,因為我們只知道

    shapes Shape 或者其子類型的容器,然而具體類型是什么不知道,它未必是 Rectangle 的父類,所以不能放置元素進去。

    ?

    總結起來,我們要了解的事情有:

    l???????? 泛型的用意

    l???????? 泛型的幾種形式(普通,通配符,受限通配符)

    l???????? 泛型與繼承關系一起使用時的易錯傾向,尤其是向泛型容器添加元素的情況。

    posted on 2006-08-22 11:11 Binary 閱讀(545) 評論(1)  編輯  收藏 所屬分類: j2se

    評論

    # re: generic-泛型/類屬  回復  更多評論   

    學到不少。很想交朋友請教。
    2006-09-04 17:56 | liping
    主站蜘蛛池模板: 一二三四在线播放免费观看中文版视频 | 亚洲AV日韩AV永久无码绿巨人| 无码人妻精品一二三区免费| 免费网站观看WWW在线观看| 亚洲七久久之综合七久久| 亚洲国产成人久久综合一| 久久久久久久亚洲精品| 四虎成人免费网址在线| 国内精品免费麻豆网站91麻豆 | 亚洲五月午夜免费在线视频| 四虎免费在线观看| 中文字幕人成无码免费视频| 污视频在线观看免费| 两性色午夜视频免费网| 狠狠热精品免费观看| 麻豆国产人免费人成免费视频 | 亚洲第一二三四区| 亚洲成年人在线观看| 亚洲欧洲日产国码无码网站| 日本免费人成在线网站| 久久青草精品38国产免费| sihu国产精品永久免费| 一级A毛片免费观看久久精品 | 午夜国产精品免费观看| 亚洲一区免费视频| 最近高清中文字幕免费| 最近2022中文字幕免费视频| 3d动漫精品啪啪一区二区免费| 日本不卡免费新一区二区三区 | 亚洲av无码精品网站| 亚洲成a人片在线观看无码| 亚洲国产精品VA在线看黑人| 亚洲欧洲美洲无码精品VA| 一本久久a久久精品亚洲| 亚洲中文字幕无码日韩| 亚洲精品美女久久久久99| 久久久久久久综合日本亚洲| 亚洲AV永久无码精品成人| 亚洲一区二区电影| 亚洲欧洲日本国产| 亚洲综合久久精品无码色欲|