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

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

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

    廉頗老矣,尚能飯否

    java:從技術到管理

    常用鏈接

    統計

    最新評論

    java范型學習

    泛型不用考慮對象的具體類型。優點在于,因為不用考慮對象的具體類型所以可以對一類對象執行一定的相同操作;缺點在于,因為沒有考慮對象的具體類型所以就不能使用對象自帶的接口函數。泛型的最佳用同是實現容器類。在java中,范型是在編譯器中實現的,而不是在虛擬機中實現的,虛擬機對范型一無所知。因此,編譯器一定要把范型類修改為普通類,才能夠在虛擬機中執行。在java中,這種技術稱之為“擦除”,也就是用Object類型替換范型(Comparable來替換所有范型)。當需要用到其他約束中定義的方法的時候,通過插入強制轉化代碼來實現。Wildcard支持另外一個關鍵字super,而范型方法不支持super關鍵字。下面是一個簡單的泛型類的代碼

    package demo;

    public class Name<T> {

     public Name() {
      this.firstName = null;
      this.secondName = null;
     }

     public Name(T firstName, T secondName) {
      this.firstName = firstName;
      this.secondName = secondName;
     }

     public T getFirstName() {
      return firstName;
     }

     public void setFirstName(T firstName) {
      this.firstName = firstName;
     }

     public T getSecondName() {
      return secondName;
     }

     public void setSecondName(T secondName) {
      this.secondName = secondName;
     }

     private T firstName;
     
     private T secondName;

    }

    ==================================================================

    package demo;

    public class Name {
     public Name() {
      this.firstName = null;
      this.secondName = null;
     }

     public Name(Object firstName, Object secondName) {
      this.firstName = firstName;
      this.secondName = secondName;
     }

     public Object getFirstName() {
      return firstName;
     }

     public void setFirstName(Object firstName) {
      this.firstName = firstName;
     }

     public Object getSecondName() {
      return secondName;
     }

     public void setSecondName(Object secondName) {
      this.secondName = secondName;
     }

     private Object firstName;
     
     private Object secondName;

    }


    每當你用一個具體類去實例化該范型時,編譯器都會在原生類的基礎上,通過強制約束和在需要的地方添加強制轉換代碼來滿足需求,但是不會生成更多的具體的類。
    Pair<Employee>  buddies  =  new  Pair<Employee>();

    在上述原生代碼中,此處參數類型是Object,理論上可以接納各種類型,但編譯器通過強制約束在此使用Employee(及子類)類型的參數,其他類型編譯器一律報錯buddies.setFirst(new Employee("張三")); 在上述原生代碼中,getFirst()的返回值是一個Object類型,是不可以直接賦給類型為Employee的buddy的,但編譯器在此做了手腳,添加了強制轉化代碼,實際代碼應該是Employee buddy = (Employee)buddies.getFirst();這樣就合法了。但編譯器做過手腳的代碼你是看不到的,他是以字節碼的形式完成的。Employee buddy = buddies.getFirst();一般情況下不要涉及類型的具體信息。范型類可以繼承自某一個父類,或者實現某個接口,或者同時繼承父類并且實現接口。這樣的話,就可以對類型調用父類或接口中定義的方法了。
    public class Pair<T extends Comparable>
    ...{
       public boolean setSecond(T newValue) ...{
       boolean flag = false;
       If(newValue.compareTo(first)>0) ...{
         second = newValue;
         flag = true;
       }
       return flag;
    }
     
       private T first;
       private T second;
    }

    上面的范型T被添加了一個約束條件,那就是他必須實現Comparable接口,這樣的話,就可以對范型T使用接口中定義的方法了,也就可以實現2個元素大小的比較。為了簡化范型的設計,無論是繼承類還是實現接口,一律使用extends關鍵字。若同時添加多個約束,各個約束之間用“&”分隔,比如:public class Pair<T extends Comparable & Serializable>。那么編譯器是如何處理這種情況呢?前面講過,范型類最終都會被轉化為原生類。在前面沒有添加約束的時候,編譯器將范型通通替換為Object;而增加了約束之后,通通用第一個約束來替換范型
    ArrayList<Integer> l = new ArrayList<Integer>();
        test(l);  //此處編譯器會報錯!!
    Integer確實是Number的子類,但是,ArrayList<Integer>并不是ArrayList<Number>的子類,二者之間沒有任何的繼承關系
     public static void test(ArrayList<Number> l) ...{
            l.add(new Float(2));
        }

     在函數內部,我們把Float類型的元素插入到鏈表中。因為鏈表是Number類型,這條語句沒問題。但是,如果實參是一個Integer類型的鏈表,他能存儲Float類型的數據嗎??顯然不能,這樣就會造成運行時錯誤。于是,編譯器干脆就不允許進行這樣的傳遞。在向容器類添加內容的時候可能造成類型不匹配。
    ===================================================================

    //     1.在定義方法的時候使用Wildcard(也就是下述代碼中的問號)。
        public static void test1(ArrayList<? extends Number> l) ...{
            Integer n = new Integer(45);
            Number x = l.get(0); //從鏈表中取數據是允許的
            l.add(n);  //錯誤!!往鏈表里面插入數據是被編譯器嚴格禁止的!!
        }

    //     2.定義一個范型方法。代碼如下:
        public static <T extends Number> void test2(ArrayList<T> l) ...{
            Number n = l.get(0);
            T d = l.get(0);
            l.add(d);  //與上面的方法相比,插入一個范型數據是被允許的,相對靈活一些
            l.add(n);  //錯誤!!只可以插入范型數據,絕不可插入具體類型數據。
        }

    只要我們對形參添加了一定的約束條件,那么我們在傳遞實參的時候,對實參的嚴格約束就會降低一些。上述代碼都指定了一個類Number,并用了extends關鍵字,因此,在傳遞實參的時候,凡是從Number繼承的類組成的鏈表,均可以傳遞進去。但上面代碼的注釋中也說的很清楚,為了不出現運行時錯誤,編譯器會對你調用的方法做嚴格的限制:凡是參數為范型的方法,一律不需調用!!

     

        public static void test5(ArrayList<? super Integer> l) ...{
            Integer n = new Integer(45);
            l.add(n);  //與上面使用extends關鍵字相反,往鏈表里面插入指定類型的數據是被允許的。
            Object x = l.get(0); //從鏈表里取出一個數據仍然是被允許的,不過要賦值給Object對象。
            l.add(x);   //錯誤!!將剛剛取出的數據再次插入鏈表是不被允許的。
        }

    對實參的限制更改為:必須是指定類型的父類。這里我們指定了Integer類,那么實參鏈表的元素類型,必須是Number類及其父類。下面我們重點討論一下上述代碼的第四條語句,為什么將剛剛取出的數據再次插入鏈表不被允許??道理很簡單,剛剛取出的數據被保存在一個Object類型的引用中,而鏈表的add方法只能接受指定類型Integer及其子類,類型不匹配當然不行。 

        //幫助函數
        public static <T>void helperTest5(ArrayList<T> l, int index) ...{
            T temp = l.get(index);
            l.add(temp);
        }
       
        //主功能函數
        public static void test5(ArrayList<? super Integer> l) ...{
            Integer n = new Integer(45);
            l.add(n); 
            helperTest5(l, 0);   //通過幫助類,將指定的元素取出后再插回去。
        }
    上述兩個函數結合的原理就是:利用Wildcard的super關鍵字來限制參數的類型(范型函數不支持super,要是支持的話就不用這么麻煩了),然后通過范型函數來完成取出數據的再存儲。注意:

    //1、不可以用一個本地類型(如int   float)來替換范型
    //2、運行時類型檢查,不同類型的范型類是等價的(Pair<String>與Pair<Employee>是屬于同一個類型Pair),
    //     這一點要特別注意,即如果a instanceof Pair<String>==true的話,并不代表a.getFirst()的返回值是一個String類型
    //3、范型類不可以繼承Exception類,即范型類不可以作為異常被拋出
    //4、不可以定義范型數組
    //5、不可以用范型構造對象,即first = new T(); 是錯誤的
    //6、在static方法中不可以使用范型,范型變量也不可以用static關鍵字來修飾
    //7、不要在范型類中定義equals(T x)這類方法,因為Object類中也有equals方法,當范型類被擦除后,這兩個方法會沖突
    //8、根據同一個范型類衍生出來的多個類之間沒有任何關系,不可以互相賦值
    //     即Pair<Number> p1;  Pair<Integer> p2;   p1=p2;  這種賦值是錯誤的。
    //9、若某個范型類還有同名的非范型類,不要混合使用,堅持使用范型類
    //     Pair<Manager> managerBuddies = new Pair<Manager>(ceo, cfo);
    //     Pair rawBuddies = managerBuddies;  這里編譯器不會報錯,但存在著嚴重的運行時錯誤隱患



    柳德才
    13691193654
    18942949207
    QQ:422157370
    liudecai_zan@126.com
    湖北-武漢-江夏-廟山

    posted on 2009-04-16 23:31 liudecai_zan@126.com 閱讀(1105) 評論(0)  編輯  收藏 所屬分類: 程序人生

    主站蜘蛛池模板: 18女人水真多免费高清毛片| 最近免费中文字幕中文高清 | 成人午夜免费福利| 久久av无码专区亚洲av桃花岛| 亚洲免费一区二区| 自拍偷自拍亚洲精品情侣| 一级a性色生活片久久无少妇一级婬片免费放 | 亚洲成Av人片乱码色午夜| 怡红院免费全部视频在线视频| 亚洲成AV人在线播放无码| 久久成人免费大片| 久久精品a亚洲国产v高清不卡| 精品无码免费专区毛片| va天堂va亚洲va影视中文字幕| 亚洲国产日韩一区高清在线 | 亚洲一区二区免费视频| 亚洲成人黄色网址| 夫妻免费无码V看片| 亚洲丰满熟女一区二区哦| yy6080亚洲一级理论| 亚洲a级在线观看| 最近最新的免费中文字幕| 国产成人精品日本亚洲11| 日本最新免费不卡二区在线| 老司机亚洲精品影院在线观看| 全亚洲最新黄色特级网站 | 丁香亚洲综合五月天婷婷| 99re6在线视频精品免费| 亚洲资源在线视频| 成年女人毛片免费视频| 在线播放免费人成视频网站 | 国产精品亚洲产品一区二区三区| 青青青国产手机频在线免费观看| 亚洲人成黄网在线观看| 亚洲&#228;v永久无码精品天堂久久| yellow视频免费看| 亚洲区视频在线观看| 国产99视频精品免费视频7| 免费人成在线观看视频高潮| 亚洲中文字幕无码av| 国产亚洲人成无码网在线观看|