Java 学习笔记9-泛型

泛型

什么是泛型

  • 使用ArrayList存储String类型的缺点:

    • 需强制转换;
    • 不方便,易出错;
  • 泛型即定义一种模板来适应任意类型,如ArrayList<T>,然后在代码中为用到的类创建对应ArrayList<类型>

      ArrayList<String> strList = new ArrayList<String>();
      strList.add("cunyu");
      String str = strList.get(0);
    
  • 向上转型:ArrayList<T>实现了List<T>接口,可以向上转型为List<T>

      public class ArrayList<T> implements List<T>{
          ...
      }
    
      List<String> list = new ArrayList<String>();
    
  • 泛型的好处:使用时无需对类型进行强制转换,通过编译器对类型进行检查;

  • 泛型的继承关系:T(即类型)不能变,如可以将ArrayList<Integer>向上转型为List<Integer>

使用泛型

  • 编译器能自动推断出泛型类型,因此下例两种写法等价;

      List<String> list = new List<>();
      List<String> list = new List<String>();
    
  • 泛型接口:除了ArrayList<T>使用了泛型,还可以在接口中使用泛型,但在使用时必须实现这个接口;

      // 利用泛型接口进行字符串数组排序
      import java.util.Arrays;
    
      public class Main{
          public static void main(String[] args) throws Exception {
              String[] ss = new String[] {"Apple", "Huawei", "Xiaomi", "Vivo"};
              Arrays.sort(ss);
              System.out.println(Arrays.toString(ss));
          }
      }
    
  • 不指定泛型参数类型是,编译器会发出警告,且只能将<T>视为Object类型;

编写泛型

  • 编写泛型类的步骤;

      1. 按照某类型来编写类;
           2. 标记所有特定类型;
       3. 将特定类型替换为`T`,同时申明`<T>`;
    
      public class Pair<T>{
          private T first;
          private T last;
    
          public Pair(T first, T last){
              this.first = first;
              this.last = last;
          }
    
          public T getFirst(){
              return first;
          }
    
          public T getLast(){
              return last;
          }
      }
    
  • 注意编写泛型类是,泛型类型<T>不能用于静态方法;

      // 编译错误
      public static Pair<T> create(T first, T last){
          return new Pari<T>(first, last);
      }
    
  • 同时定义多个泛型类型;

      public class Pair<T, K> {
          private T first;
          private K last;
          public Pair(T first, K last) {
              this.first = first;
              this.last = last;
          }
          public T getFirst() { ... }
          public K getLast() { ... }
      }
    

擦拭法(Type Erasure)

  1. 定义

指虚拟机对泛型一无所知,所有工作均由编译器执行,Java中的泛型实现方式即为擦拭法;

  1. Java使用擦拭法实现泛型的后果
  • 编译器将类型<T>看做Object
  • 编译器会根据<T>实现安全的强制转型;
  1. 泛型的局限
  • <T>不是基本类型;

      Pari<int> p = new Pair<>(1, 2); // 编译会出错
    
  • 无法取得带泛型的Class

      Pair<String>.class // 编译出错
    
  • 无法判断带泛型的Class

      x instanceof Pair<String>; // 编译出错
    
  • 不能实例化<T>类型;

      T last = new T(); // 编译错误
    
  1. 泛型继承
 public class IntPair extends Pair<Integer>{
     // IntPair继承自Pair
     ...
 }
  1. Java类型系统结构

extends通配符

  1. 使用extends统配负表示可以读,但是不能写;

使用类似<? extends Number>通配符作为方法参数时表示:

  • 方法内部可调用获取Number引用的方法,如Number n = obj.getFirst();
  • 方法内部无法调用传入Number引用的方法(null除外),如obj.setFirst(Number n);
  1. 使用类似<T extends Number>定义泛型时表示:泛型类型限定为NumberNumber的子类;

super通配符

泛型和发射

发布了138 篇原创文章 · 获赞 72 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/github_39655029/article/details/105448527
今日推荐