// 下列的添加方法完全没问题
      list.add("one");
      list.add(1);
     ​
      // 取的时候, 如果你小心的,也没问题
      // 需要强转, 内部是以Object引用来存放
      String s = (String) list.get(0);
      int    i = (int) list.get(1);
     ​
      // 但是如果, 不小心在获取时 类型判断出错的话
      for (int index = 0; index < list.size(); index++) {
      String str = (String) list.get(index);
      // index = 1时, 抛出java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
      }
    
*   泛型的分类
    
    *   泛型类

*   ``` public class Holder<T> {
      private T obj;
      public Holder(T t) {
      obj = t;
      }
      public void put(T t) {
      obj = t;
      }
      public T get() {
      return obj;
      }
     }
    
    *   泛型接口

    *   泛型方法

*   ``` // 普通类中的泛型方法
     public class Normal {
      // 成员泛型方法
      public <E> String getString(E e) {
      return e.toString();
      }
      // 静态泛型方法
      public static <V> void printString(V v) {
      System.out.println(v.toString());
      }
     }
     // 泛型类中的泛型方法
     public class Generics<T> {
      // 成员泛型方法
      public <E> String getString(E e) {
      return e.toString();
      }
      // 静态泛型方法
      public static <V> void printString(V v) {
      System.out.println(v.toString());
      }
     }
    
*   泛型的做用
    
    *   **能够对类型进行限定**

    *   **在编译期对类型进行检查,编译时报错**

    *   **对于获取明确的限定类型,无需进行强制类型转化**

    *   **具有良好的可读性和安全性**

*   通配符
    
    *   协变和逆变

*    f(⋅)是逆变(contravariant)的,当A≤B时有f(B)≤f(A)成立;
     f(⋅)是协变(covariant)的,当A≤B时有f(A)≤f(B)成立;
    
    *   上界通配符 —— 协变

*   `<? extends>`
    
    *   下界通配符 —— 逆变

*   `<? super>`
    
*   注意点
    
    *   泛型类中静态方法不能使用泛型参数

    *   泛型接口中不能使用类型参数作为成员变量


*   实现原理即类型擦除
    
    *   泛型只是给编译器用来检查类型的


*   参考
    
    *   [java泛型深度解读](https://www.jianshu.com/p/cc793713a992)

    *   [Java中的逆变与协变](https://www.cnblogs.com/en-heng/p/5041124.html)

    *   [java泛型 通配符详解及实践](https://www.jianshu.com/p/e3d58360e51f)

zeronlee
112 声望13 粉丝