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

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

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

    人在江湖

      BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
      82 Posts :: 10 Stories :: 169 Comments :: 0 Trackbacks

    從JDK1.4到JDK5中間經歷了兩年半左右的時間,從JDK5到JDK6經歷了兩年左右的時間,從JDK6到JDK7經歷了4年半多的時間。JDK5,6,7這三個版本,只有JDK5有橫空出世的驚艷,一系列new feature明顯改變了Java程序員日常的coding工作:Generics, Annotation, Autoboxing, for each statement.... 其中Java Generics是一個大的新feature. 相較于C++ templates, Java Generics有諸多限制和陷阱,所以用起來有些不爽, 但越是陷阱多,越有必要好好學學。Thinking in java 第四版除了最后一章GUI外一共900頁,其中Generics這一章就90多頁,這篇博客主要是Thinking in java的Generics這章的筆記。

     

    Java Generics 可以應用于Class和Interface,比如:

    public class LinkedStack<T>{}

    public interface Generator<T> {}

    也可以應用于方法,比如:

    public <T> void f(T x) { }

    使用泛型時,需要時時牢記的是,運行時的泛型代碼中不真的保留泛型參數類型(There’s no information about generic parameter types available inside generic code.  )所以運行時,List<String>和List<Integer>是一回事。

     

    注意泛型不總是實用,比如:

       1: class Manipulator2<T extends HasF> { 
       2:   private T obj; 
       3:   public Manipulator2(T x) { obj = x; } 
       4:   public void manipulate() { obj.f(); } 
       5: } 

    完全可以替代成:

       1: class Manipulator3 { 
       2:   private HasF obj; 
       3:   public Manipulator3(HasF x) { obj = x; } 
       4:   public void manipulate() { obj.f(); } 
       5: } 

    但是如果原本的code有一點變化,泛型帶來的好處就體現出來了:

       1: class ReturnGenericType<T extends HasF> { 
       2:   private T obj; 
       3:   public ReturnGenericType(T x) { obj = x; } 
       4:   public T get() { return obj; } 
       5: } 

    注意這個例子里get()方法返回了特定的類型T。

     

    因為run time時泛型丟掉了真正的類型,所以一些操作是不被允許的:

       1: public class Erased<T> { 
       2:   private final int SIZE = 100; 
       3:   public static void f(Object arg) { 
       4:     if(arg instanceof T) {}          // Error 
       5:     T var = new T();                 // Error 
       6:     T[] array = new T[SIZE];         // Error 
       7:     T[] array = (T)new Object[SIZE]; // Unchecked warning 
       8:   } 
       9: } 

    這時候可以顯式地傳入Class object參數,書里稱之為Type Tag

       1: public class ClassTypeCapture<T> { 
       2:   Class<T> kind; 
       3:   public ClassTypeCapture(Class<T> kind) { 
       4:     this.kind = kind; 
       5:   } 
       6:  
       7:   public boolean f(Object arg) { 
       8:     return kind.isInstance(arg); 
       9:   }  
      10: }

    Dimension是Class, HasColor是Interface, 可以有如下的寫法

    class ColoredDimension<T extends Dimension & HasColor> { }

    注意extends后可以有多項,這與Class的繼承不同,并且,Class要放在Interface前面

     

    注意Array對數據類型檢查是很嚴格的:

       1: class Fruit {} 
       2: class Apple extends Fruit {} 
       3: class Jonathan extends Apple {} 
       4: class Orange extends Fruit {} 
       5:  
       6: public class CovariantArrays { 
       7:   public static void main(String[] args) { 
       8:     Fruit[] fruit = new Apple[10]; 
       9:     fruit[0] = new Apple(); // OK 
      10:     fruit[1] = new Jonathan(); // OK 
      11:     // Runtime type is Apple[], not Fruit[] or Orange[]: 
      12:     try { 
      13:       // Compiler allows you to add Fruit: 
      14:       fruit[0] = new Fruit(); // ArrayStoreException 
      15:     } catch(Exception e) { System.out.println(e); } 
      16:     try { 
      17:       // Compiler allows you to add Oranges: 
      18:       fruit[0] = new Orange(); // ArrayStoreException 
      19:     } catch(Exception e) { System.out.println(e); } 
      20:   } 
      21: } 

    注意這一句,Fruit[] fruit = new Apple[10]; 實際類型是Apple,那么fruit里就不能加入Fruit或Orange了.

     

    Container不存在upcast, 別混淆了被包含的元素:

       1: public class NonCovariantGenerics { 
       2:   // Compile Error: incompatible types: 
       3:   List<Fruit> flist = new ArrayList<Apple>(); 
       4: }

    如果非要upcast的話可以這樣寫:

    List<? extends Fruit> flist = new ArrayList<Apple>(); 

    需要注意的是,flist不能再往里加new Apple()或new Fruit()或任何東西了,因為compiler看到List<? extends Fruit>, 就會認為里面可能是Apple,也可能是Orange, 你往里填什么他都不認為一定對。

     

    如果想往List里添加,可以這樣寫:

       1: public class SuperTypeWildcards { 
       2:   static void writeTo(List<? super Apple> apples) { 
       3:     apples.add(new Apple()); 
       4:     apples.add(new Jonathan()); 
       5:     // apples.add(new Fruit()); // Error 
       6:   } 
       7: } 

     

     

    代碼片段:

     

       1: static <T> 
       2:  T wildSubtype(Holder<? extends T> holder, T arg) { 
       3:    // holder.set(arg); // Error: 
       4:    //   set(capture of ? extends T) in 
       5:    //   Holder<capture of ? extends T> 
       6:    //   cannot be applied to (T) 
       7:    T t = holder.get(); 
       8:    return t; 
       9:  }  
      10:  static <T> 
      11:  void wildSupertype(Holder<? super T> holder, T arg) { 
      12:    holder.set(arg); 
      13:    // T t = holder.get();  // Error: 
      14:    //   Incompatible types: found Object, required T 
      15:  
      16:    // OK, but type information has been lost: 
      17:    Object obj = holder.get(); 
      18:  } 

     

    <? extends T> 和 <? super T>兩者中,前者適合get到特定類型T, 但是不能做set操作。后者相反, 可以set特定類型,但是不能get到特定類型。

     

    Holder, Holder<?>這兩個類不一樣,Holder代表可以包含任何類型,Holder<?>代表可以包含一系列同種類型,但不知道是哪種類型,甚至于你不能往里面加入Object

    posted on 2012-08-20 08:13 人在江湖 閱讀(7149) 評論(0)  編輯  收藏 所屬分類: java
    主站蜘蛛池模板: caoporn国产精品免费| 亚洲制服丝袜中文字幕| 国产又黄又爽又大的免费视频| 在线观看亚洲免费| 校园亚洲春色另类小说合集| 暖暖免费高清日本一区二区三区| 亚洲国产成人手机在线观看| 四虎影视在线永久免费看黄| 日韩亚洲人成在线综合| www.亚洲精品| 国产一级婬片A视频免费观看| 久久亚洲国产欧洲精品一| 久操视频免费观看| 亚洲色图校园春色| 拨牐拨牐x8免费| 亚洲欧美日韩中文二区| 免费大黄网站在线看| 一区二区三区免费高清视频| 亚洲国产精品福利片在线观看 | 相泽南亚洲一区二区在线播放| 国产免费观看a大片的网站| 暖暖免费中文在线日本| 亚洲AV无码专区国产乱码电影| 免费视频爱爱太爽了| 亚洲丶国产丶欧美一区二区三区| 亚洲AV成人精品日韩一区18p| 手机看片国产免费永久| 亚洲第一永久在线观看| 小小影视日本动漫观看免费| 亚洲高清免费视频| 亚洲午夜电影一区二区三区| 国产在线a不卡免费视频| 久久福利青草精品资源站免费| 亚洲精品中文字幕乱码| 国产免费av一区二区三区| 中文成人久久久久影院免费观看| 亚洲在成人网在线看| 婷婷亚洲天堂影院| 3d动漫精品啪啪一区二区免费| 亚洲日韩一区精品射精| 亚洲色精品vr一区二区三区|