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

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

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

    隨筆 - 22, 文章 - 0, 評論 - 1, 引用 - 0
    數(shù)據(jù)加載中……

    java泛型學習筆記

    本文為從網(wǎng)上東拼西湊的java泛型學習筆記,摘出了我認為有價值的部分,尚未整理,先放在這里備份。
    泛型在類、接口和方法中定義,在實現(xiàn)(extends,implements)和實例化時使用。
    定義類或接口時,使用"<E extends Fruit>"這種形式,之后就可以在類中對E進行操作。
    定義方法所接收的參數(shù)時,使用"List<? extends Fruit>"這種形式,就可以接收這個范圍的List做參數(shù)。
    實例化時,不能使用問號這種形式來指定泛型——不能new List<? extends Apple>();
    繼承或實現(xiàn)時,也不能使用問號這種形式來指定泛型——不能public interface MyList extends List<? extends Apple>
    關于extends和super關鍵字的PECS(producer-extends, consumer-super)原則:
    如果參數(shù)化類型表示一個T生產者,就使用<? extends T>,因為它只能get,用于將數(shù)據(jù)從生產者取出(只要生產者可以生產T的子類,那就一定可以生產T);
    如果參數(shù)化類型表示一個T消費者,就使用<? super T>,因為它只能add,用于將數(shù)據(jù)add入消費者(只要消費者可以消費T的超類,那就一定可以消費T)。

    泛型的繼承原則:
    1,相同類型參數(shù)的泛型類的關系取決于泛型類自身的繼承體系結構。即List<String>是Collection<String> 的子類型,List<String>可以替換Collection<String>。這種情況也適用于帶有上下界的類型聲明。
    2,當泛型類的類型聲明中使用了通配符的時候, 其子類型可以在兩個維度上分別展開。如對Collection<? extends Number>來說,其子類型可以在Collection這個維度上展開,即List<? extends Number>和Set<? extends Number>等;也可以在Number這個層次上展開,即Collection<Double>和 Collection<Integer>等。如此循環(huán)下去,ArrayList<Long>和 HashSet<Double>等也都算是Collection<? extends Number>的子類型。
    3,如果泛型類中包含多個類型參數(shù),則對于每個類型參數(shù)分別應用上面的規(guī)則。
    泛型的定義原則:
    1,泛型類與一般的Java類基本相同,只是在類和接口定義上多出來了用<>聲明的類型參數(shù)。
    2,一個類可以有多個類型參數(shù),如 MyClass<X, Y, Z>。
    3,每個類型參數(shù)在聲明的時候可以指定上界。
    4,所聲明的類型參數(shù)在Java類中可以像一般的類型一樣作為方法的參數(shù)和返回值,或是作為域和局部變量的類型。
    5,由于類型擦除機制,類型參數(shù)并不能用來創(chuàng)建對象或是作為靜態(tài)變量的類型。
    如果沒有向后兼容性顧慮,那么Collection框架會這么設計(而實際上不是):
    interface Collection<E> { 
      public T[] toArray(Class<T super E> elementClass); 
     }
    這樣很通用,假設E是Apple類,那么傳入任何一個Apple的父類(例如Fruit)都合法,會返回Fruit數(shù)組。
    如果傳入Object,那就相當于現(xiàn)在Collection接口的Object[] toArray()方法了。
    同樣,如果沒有向后兼容性顧慮,那么Collection框架的remove和removeAll會這么寫(而實際上不是):
    interface Collection<E> { 
      public boolean remove(E e);  // not really 
      public void removeAll(Collection<? extends E> c);  // not really 
     } 
    缺陷是:只能傳入當前泛型的兼容類型,不能傳入任意Object或Collection<Object>——這樣無法到兼容之前的API定義。
    不能創(chuàng)建泛型類型的對象,因為編譯器不知道要調用什么構造函數(shù)。如果泛型類需要構造用泛型類型參數(shù)來指定類型的對象,那么構造函數(shù)應該接受類文字(Foo.class)并將它們保存起來,以便通過反射創(chuàng)建實例(類似于上述Collection的toArray方法)
    類型安全的異構容器(內部用Map<Class<?>,Object>來實現(xiàn)):
    public class Favorites {
         public <T> void putFavorite(Class<T> type,T instance);
         public <T> T getFavorite(Class<T> type);
    }
    例如用于數(shù)據(jù)庫不定數(shù)目的columns:每個cell的數(shù)據(jù)都以這種方式指定類型保存Favorites到容器中,再將此容器當作元素保存到更上層的結果容器中。
    不能實例化泛型類型的數(shù)組:new List<String>[3]是不合法的。
    但是在可以確定類型的情況下,將Object數(shù)組強制轉換成泛型數(shù)組是合法的,例如ArrayList的源碼:return (T[]) Arrays.copyOf(elementData, size, a.getClass());

    泛型方法:
    聲明方法時將用到的類型參數(shù)列在前面即可(所在類上不需要定義此參數(shù)類型):
    public static <E> Set<E> union(Set<E> s1,Set<E> s2) ;
    靜態(tài)工具方法特別適合這樣寫。
    一般來說編寫java泛型方法時,返回值類型和至少一個參數(shù)類型應該是泛型,而且類型應該是一致的,如果只有返回值類型或參數(shù)類型之一使用了泛型,這個泛型方法的使用就大大的限制了,基本限制到跟不用泛型一樣的程度。
    第一種:public static <T extends CommonService> T getService(Class<T> clazz);
    NoticeService noticeService=CommonService.getService(NoticeService.class);//正確的使用第一種泛型方法,不會出現(xiàn)編譯錯誤。
    NoticeService noticeService=CommonService.getService(UserService.class);//不正確的使用第一種泛型方法,會出現(xiàn)編譯錯誤。
    第二種:public static <T> T getService(Class<? extends CommonService> clazz);
    NoticeService noticeService=CommonService.getService(NoticeService.class);//正確的使用第二種泛型方法,不會出現(xiàn)編譯錯誤,邏輯也正確,運行時不會出現(xiàn)異常。
    NoticeService noticeService=CommonService.getService(UserService.class);//不正確的使用第二種泛型方法,不會出現(xiàn)編譯錯誤,但邏輯不正確,運行時會出現(xiàn)異常,危險!
    --
    網(wǎng)上不少關于泛型的說明很好,可是不知道是不是jdk版本問題,居然沒辦法實際通過編譯,于是我只好自己在jdk1.7下一一重寫和嘗試,最后加上總結和注釋,如下:

    1 public class Fruit{
    2     
    3 }

    1 public class Apple extends Fruit {
    2     
    3 }

     1 public class Basket{
     2     //從泛型化的list中取出Fruit,里面的元素一定是Fruit的子類,所以都可以當作Fruit返回
     3     public static Fruit getFruit(List<? extends Fruit> list){
     4         return list.get(0);
     5     }
     6     
     7     //將Apple放入泛型化的list(這個list可以接收的類型是Apple的父類,所以一定可以接收apple或apple的子類)
     8     public static void addApple(List<? super Apple> list,Apple apple){
     9         list.add(apple);
    10     }
    11 }

     1 public class GenericTester extends AbstractTester{
     2     public void test1(){
     3         List<Apple> appleList = new ArrayList<Apple>();
     4         appleList.add(new Apple()); //先定義List<Apple>,填入元素
     5         Fruit fruit=Basket.getFruit(appleList); //List<Apple>類型符合List<? extends Fruit>的要求
     6     }
     7     
     8     public void test2(){
     9         List<Fruit> fruitList=new ArrayList<Fruit>();
    10         Basket.addApple(fruitList, new Apple()); //List<Fruit>符合List<? super Apple>的要求
    11     }
    12 }

     1 public class GenericCompileTester {
     2     public void addInteger1(List<?> list){
     3         list.add(1); //編譯錯誤,因為問號代表“編譯時不確定,但運行時確定”的類型,Integer不一定符合要求,其實這里相當于<? extends Object>
     4     }
     5     
     6     public void addInteger2(List<Object> list){
     7         list.add(1); //編譯通過,因為編譯時和運行時都確定了是Object類型,Integer肯定符合要求
     8     }
     9     
    10     public void test(){
    11         List<String> list=new ArrayList<String>();
    12         addInteger2(list); //編譯錯誤,因為List<String>不能當作List<Object>傳入,否則數(shù)字1將被當作String添加,類型將不再安全
    13     }
    14     
    15     public void test3(){
    16         List<? extends Fruit> fruitList=new ArrayList<Apple>();
    17         fruitList.add(new Apple());    //編譯錯誤,編譯器無法確定List允許的是Fruit的具體哪一個子類
    18         fruitList.add(new Fruit());    //編譯錯誤,編譯器無法確定List允許的是Fruit的具體哪一個子類
    19     }
    20     
    21     public void test4(){
    22         List<? super Apple> fruitList=new ArrayList<Fruit>();
    23         fruitList.add(new Apple());    //編譯通過,Apple和Apple的子類都可以保證符合條件要求
    24         fruitList.add(new Fruit());    //編譯錯誤,編譯器無法確定List允許的是Apple的具體那個級別的父類或接口
    25     }
    26 }

    posted on 2012-08-22 03:17 王星游 閱讀(485) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 亚洲av成人综合网| 久久国产亚洲观看| 日韩精品亚洲aⅴ在线影院| 国产日产亚洲系列最新| 亚洲国产成人片在线观看| 亚洲黄色三级网站| a级毛片在线免费| 少妇人妻偷人精品免费视频| 182tv免费视视频线路一二三| 99re热免费精品视频观看| 日本免费人成黄页网观看视频| 亚洲精品无码激情AV| 国产∨亚洲V天堂无码久久久| 亚洲精品偷拍无码不卡av| 亚洲日韩精品无码专区加勒比☆| 看一级毛片免费观看视频| 国内永久免费crm系统z在线| 99视频全部免费精品全部四虎| 日韩一品在线播放视频一品免费| 亚洲精品无码久久久久AV麻豆| 99亚洲精品高清一二区| 亚洲精华国产精华精华液| 成人毛片100免费观看| 成人在线免费看片| 国产99视频精品免费视频7| 区久久AAA片69亚洲| xxx毛茸茸的亚洲| 一级一黄在线观看视频免费| 3d动漫精品啪啪一区二区免费| 国产成人免费网站在线观看| 国产亚洲精AA在线观看SEE| 自拍日韩亚洲一区在线| 成人免费视频一区二区| 98精品全国免费观看视频| 国产无遮挡色视频免费视频| 亚洲成a人片在线观看中文动漫| 亚洲人成未满十八禁网站| 国内精品免费在线观看| 国产精品免费看久久久无码| 久久精品亚洲视频| 美女尿口扒开图片免费 |