<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 閱讀(2693) 評論(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
    這種語法真的很丑陋,難道在像匯編回歸?
    主站蜘蛛池模板: 国产中文字幕免费观看| 你懂得的在线观看免费视频| 中文字幕成人免费视频| 精品久久久久久亚洲| 精品国产污污免费网站入口| 亚洲人午夜射精精品日韩| 添bbb免费观看高清视频| 日产国产精品亚洲系列| 美女视频免费看一区二区| 国产免费69成人精品视频| 男女污污污超污视频免费在线看| 免费萌白酱国产一区二区| 人妻仑乱A级毛片免费看| 国产精品亚洲视频| 99久久国产精品免费一区二区| 亚洲AV无码一区二区乱孑伦AS| 8x8x华人永久免费视频| 亚洲w码欧洲s码免费| 午夜无遮挡羞羞漫画免费| 国产在亚洲线视频观看| 狠狠色婷婷狠狠狠亚洲综合| 精品国产一区二区三区免费| 亚洲日韩中文字幕| 午夜免费福利影院| 一级成人生活片免费看| 亚洲短视频男人的影院| 青青久在线视频免费观看| 国产成人亚洲精品电影| 亚洲综合另类小说色区| 8x网站免费入口在线观看| 亚洲日韩国产欧美一区二区三区| 日本中文一区二区三区亚洲 | 波多野结衣亚洲一级| 性色av免费观看| 无码 免费 国产在线观看91| 亚洲精品综合一二三区在线| 最近2019中文字幕免费看最新| 一区二区三区免费看| 亚洲综合无码一区二区三区| 四虎免费在线观看| 中国好声音第二季免费播放|