<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
    這種語法真的很丑陋,難道在像匯編回歸?
    主站蜘蛛池模板: 国产精品免费视频一区| 最近新韩国日本免费观看 | 国内成人精品亚洲日本语音| 很黄很污的网站免费| 亚洲桃色AV无码| 美女裸身网站免费看免费网站| 亚洲Av无码专区国产乱码DVD| 99亚洲精品卡2卡三卡4卡2卡| 国产精品视频免费一区二区| 亚洲精品第五页中文字幕| 99视频精品全部免费观看| 亚洲精品蜜桃久久久久久| a在线观看免费网址大全| 亚洲色婷婷综合久久| 日本免费久久久久久久网站| 亚洲熟妇无码AV在线播放| 国产午夜精品免费一区二区三区| 久久精品亚洲乱码伦伦中文| 国产精品免费久久久久影院| 丁香五月亚洲综合深深爱| 七色永久性tv网站免费看| 久久久亚洲精品视频| free哆啪啪免费永久| 久久亚洲中文字幕无码| 亚洲国产天堂久久久久久| 成人无码a级毛片免费| 亚洲伊人久久大香线蕉| 免费看国产一级特黄aa大片| 在线视频网址免费播放| 内射干少妇亚洲69XXX| 国产91久久久久久久免费| 国产午夜无码片免费| 亚洲中文字幕无码av永久| 国产国拍亚洲精品福利| 成年黄网站色大免费全看| 全部一级一级毛片免费看| 亚洲视频在线观看免费视频| 免费黄色一级毛片| 污污网站免费观看| 国产av无码专区亚洲av毛片搜| 亚洲精品免费观看|