【Java】泛型

299 阅读2分钟

一、什么是泛型(Generic)

泛型是JDK5引入的一种参数化类型机制

二、为什么要用泛型

  1. 将类型检查提前到编译期间
  2. 避免类型转换(避免出现运行期间ClassCastException)
  3. 提高代码的复用性(容器类)

三、泛型在Java中的使用

  1. 泛型类

    public class Box<T>{
    
    private T obj;
    
    public void setObj(T t){
    	obj = t;	
    }
    
    public T getObj(){
    	return obj;
    }
    }	
    
    
  2. 泛型接口

    public interface Animal<T>{
    	String makeSound(T t);
    }
    
  3. 泛型方法

    public<T> void print(T t){
    	System.out.print(t);
    }
    

注意:

  • 是否拥有泛型方法,与其所在的类是否是泛型没有任何关系
  • 判断一个方法是否是泛型方法,可以看是否有

四、讲讲PESC机制

producer-extens , consumer -super.

如果要从集合中读取类型T的数据,并且不能写入,可以使用 ? extends 通配符;(Producer Extends)

如果要从集合中写入类型T的数据,并且不需要读取,可以使用 ? super 通配符;(Consumer Super)

五、类型擦除(Type Erasure)

  • jvm虚拟机不支持泛型
  • List<String>和List<Integer>在运行时是相同的类型
  • 泛型擦除后,重载会产生相同的类型签名,下面代码是不能编译的
    public class UseList<T,W>{
    void f(List<T> v){}
    void f(List<W> v){}
    }
    
  • catch语句不能捕获泛型类型的异常,泛型类也不能直接或者间接继承自Throwable

六、泛型的通配符

  1. ? extend xxx(可以读取数据,不能添加数据)
  2. ? super xxx(可以添加数据,不能读取数据)
  3. ?(不确定类型)

七、泛型的限制

  1. 不支持基本数据类型
  2. 不能使用static关键字
  3. 不能使用clone
  4. 不支持数组
  5. 不是协变的,Integer extend Number,List<Integer> 和List<Number>是没有继承关系的
  6. 不能使用 arg instanceOf T
  7. 不能使用 T var = new T();
  8. 不能使用 T[] array = new T[10];