Java语言 - 泛型(Generic)

Java 5 引入了泛型(Generic), 使用泛型可以带来如下好处:

  • 代码重用
  • 不须强制类型转换 (使用类型参数type parameter)
List<String> list = new ArrayList<>();//类型参数是String
String element = list.get(0);//不须类型转换

一. 可以定义一个或多个类型参数的泛型类

public class Pair<T>
{
   private T first;
   private T second;

   public Pair() { first = null; second = null; }
   public Pair(T first, T second) { this.first = first;  this.second = second; }

   public T getFirst() { return first; }
   public T getSecond() { return second; }

   public void setFirst(T newValue) { first = newValue; }
   public void setSecond(T newValue) { second = newValue; }
}

二. 可以定义一个或多个类型参数的泛型方法

public class UnionSet {
    public static <E> Set<E> union(Set<E> source, Set<E> destination) {//泛型方法定义在普通类中
        source.addAll(destination);
        return source;
    }
}

三. 泛型类型擦除(type erased)
Java的泛型是伪泛型。在编译期间,所有的泛型信息都会被擦除掉。任何一个泛型类型都会生成一个原始类型。在生成的Java字节码中是不包含泛型中的类型信息的。

对于无限定类型,编译器翻译成Object。如上面的Pair< T >泛型类 编译器翻译成:

public class Pair 
{
   private Object first;
   private Object second;

   public Pair() { first = null; second = null; }
   public Pair(Object first, Object second) { this.first = first;  this.second = second; }

   public Object getFirst() { return first; }
   public Object getSecond() { return second; }

   public void setFirst(Object newValue) { first = newValue; }
   public void setSecond(Object newValue) { second = newValue; }
}

getClass()方法总是返回原始类型。

Pair<String> stringPair = new Pair<String>();
Pair<Double> doublePair = new Pair<Double>();
if(stringPair.getClass() == doublePair.getClass())// it is true

四. 约束和局限性

  • 不能用基本类型实例化类型参数
    Pair< double >无效,只能 Pair< Double >

  • 不能运行时对泛型类型进行类型查询

if(a instanceof Pair<String>) //Error
if(a instanceof Pair<T>) //Error
  • 不能创建参数化类型的数组
Pair<String>[] strs = new Pair<String>[10];
但可以声明 Pair<String>[] 变量。
  • 不能实例化类型变量
new T(); //Error
new T[]; //Error
T.class //Error
  • 禁止带有类型变量的静态域和方法
  • 不能抛出和捕获泛型类的实例

五. 泛型类型的继承规则

Manager 是 Employee的子类;但是List<Manager>和List<Employee>没有关系。
List<Employee> list = new ArrayList<Manager>()//Error

List<Employee> list = new ArrayList<Employee>();
list.add(new Manager());//OK

这里写图片描述

六. 通配符类型
通配符类型可以做变量,但不可实例化。

List<?> employees = new ArrayList<?>();//Error
List<? extends Employee> employees = new ArrayList<? extends Employee>();//Error

子类型限定的通配符,可以 从泛型对象读取。

List<? extends Employee> employees = new ArrayList<Manager>();//OK
Employee employee = employees.get(0);//读取

超类型限制的通配符,可以向泛型对象写入。

List<? super Manager> employees1 = new ArrayList<Employee>();//OK
employees1.add(new Manager());//写入

List<? super Manager> employees2 = new ArrayList<Object>();//OK
employees2.add(new Manager());//写入

无限定通配符,读取只能赋值给Object变量。

List<?> employees3 = new ArrayList<Manager>();
Object obj = employees3.get(0);

无限定通配符,不可写入。

List<?> employees4 = new ArrayList<Manager>();
employees4.add(new Manager());//Error
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值