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

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

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

    莊周夢蝶

    生活、程序、未來
       :: 首頁 ::  ::  :: 聚合  :: 管理

    Java泛型再學習

    Posted on 2007-06-05 17:07 dennis 閱讀(2692) 評論(2)  編輯  收藏 所屬分類: java
        泛型引入java語言已經有很長一段時間了,在JDK5出來的時候也非常認真地學習過,不過學習的資料都是網上泛濫并且重復的教程。這幾天下了《The Java Programming Language》的第4版,準備把jdk5引入的新東西再重新系統地學習一次,同時再次回顧下java基礎。今天記錄下學習泛型那一章的注意點。
    一、泛型類型的聲明
    1.需要著重注意的一點,比如聲明類Cell<E>:
    package net.rubyeye.javaprogramming.generic;

    public class Cell<E> {
        
    private Cell<E> next;

        
    private E element;

        
    public Cell(E element) {
            
    this.element = element;
        }

        
    public Cell(E element, Cell<E> next) {
            
    this.next = next;
            
    this.element = element;
        }

        
    public E getElement() {
            
    return element;
        }

        
    public void setElement(E element) {
            
    this.element = element;
        }

        
    public Cell<E> getNext() {
            
    return next;
        }

        
    public void setNext(Cell<E> next) {
            
    this.next = next;
        }

    }

    然后如此使用:
    Cell<String> strCell = new Cell<String>("Hello");
    Cell
    <Integer> intCell = new Cell<Integer>(25);

    那么Cell<String>和Cell<Integer>是兩個類嗎?不,他們是同一個類,通過下面的實驗證明:
    assertTrue(strCell.getClass() == intCell.getClass()));

    java泛型的實現采用的“擦拭法”,Cell<E>仍然是一個類,無論E被任何具體的類型所替代。

    2.泛型的類型參數不能用于static變量、static方法和static初始化,比如下面的使用方式都不能編譯通過:
    public class Cell<E> {
        
    private static Cell<E> next;
        
        
    private static void test(E e){
            
        }
       
    同樣,靜態方法是與類相關聯的,調用也只能通過類,假設Cell有一個靜態方法test,怎么調用才是正確的呢?
    Cell<E>.test();  //編譯錯誤
    Cell<String>.test();  //同樣編譯錯誤
    Cell.test();  //正確的方式
    類似的,泛型的類型參數不能用于聲明數組類型,比如下面的代碼同樣無法編譯通過:
    class SingleLinkQueue<E> {
        
    // 
        public E[] toArray() {
        
    //
        }
    }

    3.類型參數可以繼承其他的類和接口,如果有多個接口可以用&符號連接,通過extend參數限制了類型參數的范圍,比如:
    interface SortedCharSeqCollection<extends Comparable<E>
                                      
    & CharSequence> {
        
    //  sorted char sequence collection methods 
    }

    SortedCharSeqCollection的類型參數E強制繼承自Comparable和CharSequence接口,也就是替代的具體的類型參數必須實現這兩個接口,從而限制了類型參數(type parameter)。

    4.比較有趣的內部類的泛型,對于靜態內部類的類型參數可以與外部類的類型參數名不一樣,靜態內部類的類型參數與外部類的類型參數其實沒有一點關系,比如:
    class SingleLinkQueue<E> {
        
    static class Cell<E> {
            
    private Cell<E> next;
            
    private E element;
            
    public Cell(E element) {
                
    this.element = element;
            }
            
    public Cell(E element, Cell<E> next) {
                
    this.element = element;
                
    this.next = next;
            }
            
    public E getElement() {
                
    return element;
            }
            
    /*  rest of Cell methods as before  */
        }

        
    protected Cell<E> head;
        
    protected Cell<E> tail;

        
    /*  rest of SingleLinkQueue methods as before  */
    }


    Cell<E>類的聲明和SingleLinkQueue<E> 兩個類中的E僅僅是名稱相同,他們之間的關聯是通過head和tail的聲明才關聯在一起,你可以將Cell<E>中的E改成F也沒關系,比如:
    package net.rubyeye.javaprogramming.generic;

    class AnotherSingleLinkQueue<E> {
        
    static class Cell<F> {
            
    private Cell<F> next;

            
    private F element;

            
    public Cell(F element) {
                
    this.element = element;
            }

            
    public Cell(F element, Cell<F> next) {
                
    this.element = element;
                
    this.next = next;
            }

            
    public F getElement() {
                
    return element;
            }
            
    /*  rest of Cell methods as before  */
        }

        
    protected Cell<E> head;

        
    protected Cell<E> tail;

        
    /*  rest of SingleLinkQueue methods as before  */
    }

    而一般的內部類就不一樣了,內部類可以直接使用外部類的類型參數甚至隱藏。

    二、子類型與通配符
    今天讀了第2節,泛型的使用比我原先所知的更為復雜,java語法本來以簡潔優美著稱,隨著java5,java7的到來,語法是越來越復雜,甚至可以說丑陋!-_-

        要知道一點,比如List<Integer>不是List<Number>的子類,而是Collection<Integer>的子類。因為List<Integer>和List<Number>的類型是一樣的,都是List。那么如何表示參數化類型是Number的子類呢?這就需要用到通配符:
    List<? extends Number>
    表示類型變量是Number或者Number的子類。這個就是所謂的上界通配符,同樣,如果要表示類型變量是Number或者Number的super type,可以使用下界通配符:
    List<? super Number>

    而通配符List<?>等價于:
    List<? extends Object>

        通配符只能用于變量、局部變量、參數類型和返回類型,不能用于命名類和接口。比如下面的代碼將不能編譯通過:
    class MyList implements List<?>{
       
    //
    }
        通配符有另一個問題:因為通配符代表的是未知的類型,你不能在任何需要類型信息的地方使用它。比如下面的代碼同樣無法編譯通過:
    SingleLinkQueue<?> strings =
        
    new SingleLinkQueue<String>();
    strings.add(
    "Hello");               // INVALID: 無法編譯

    SingleLinkQueue
    <? extends Number> numbers =
        
    new SingleLinkQueue<Number>();
    numbers.add(Integer.valueOf(
    25));   // INVALID: 無法編譯


    三、泛型方法和類型推斷
        如果我們想參數化方法的參數和返回值的類型,這就引出了泛型方法的聲明,聲明一個泛型方法的方式如下:
    <T> T passThrough(T obj) {
        
    return obj;
    }

    這個方法限制傳入的參數的類型與返回的參數類型將一致,可以看到,在方法簽名前加上<T>即可。我們可以這樣調用這個方法:
    String s1 = "Hello";
    String s2 
    = this.<String>passThrough(s1);

    這樣的調用是不是比較奇怪?幸好提供了類型推斷,根據參數的類型來自動判斷方法的類型(比如返回值類型),因此可以直接調用:
    String s1 = "Hello";
    String s2 
    = this.passThrough(s1);

        如果方法有兩個類型變量,類型推斷將怎么處理呢?比如:
    <T> T passThrough(T obj1,T obj2) {
            
    return (T)(obj1.toString()+obj2.toString());
        }

    然后我們傳入兩個參數,一個String,一個int,那么返回什么呢?
    String s1="test";
    String s3
    =this.passThrough(s1, 1);  //編譯出錯
    類型推斷是比較復雜的,這里將返回的將是Object類型,是傳入的參數類型的交集


    評論

    # re: Java泛型再學習  回復  更多評論   

    2011-08-04 10:37 by wangxt+
    2.泛型的類型參數不能用于static變量、static方法和static初始化,比如下面的使用方式都不能編譯通過:
    對這點很傷心

    # re: Java泛型再學習[未登錄]  回復  更多評論   

    2012-07-11 15:02 by ivy
    這種語法真的很丑陋,難道在像匯編回歸?
    主站蜘蛛池模板: 亚洲国产精品特色大片观看完整版| 丁香婷婷亚洲六月综合色| 亚洲成a人片在线观看日本| 男人j进女人p免费视频| 免费AA片少妇人AA片直播| 亚洲精品中文字幕乱码影院| 精品熟女少妇av免费久久| 亚洲欧洲日韩综合| 国内精品乱码卡1卡2卡3免费| 久久精品国产亚洲av麻豆蜜芽| 国产精品成人免费福利| 亚洲日日做天天做日日谢| 日本不卡在线观看免费v| 亚洲欧洲日产国码在线观看| 精品成在人线AV无码免费看| 亚洲中文字幕无码一久久区| 两个人看的www免费视频中文| 日韩一级免费视频| 成人精品综合免费视频| 亚洲精品无码精品mV在线观看| 国产亚洲日韩在线a不卡| 搡女人真爽免费视频大全| 老子影院午夜伦不卡亚洲| 在线观看视频免费完整版| 精品亚洲成A人在线观看青青| 免费日本黄色网址| 亚洲AV成人一区二区三区观看 | 国产免费伦精品一区二区三区 | 成年在线网站免费观看无广告 | 亚洲一区二区三区免费观看| 成人免费a级毛片| 人妻18毛片a级毛片免费看| 亚洲AV无码成人专区片在线观看| 一级特级女人18毛片免费视频| 国产精品亚洲精品日韩已满| 人成午夜免费视频在线观看| 全部一级一级毛片免费看| 亚洲理论片中文字幕电影| 国产免费av片在线播放| 午夜免费福利小电影| 久久久久亚洲AV无码去区首|