Java语言

来源:互联网 发布:李鸿章后人知乎 编辑:程序博客网 时间:2024/06/03 16:04

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

  • 代码重用
  • 不须强制类型转换 (使用类型参数type parameter)
List<String> list = new ArrayList<>();//类型参数是StringString 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>) //Errorif(a instanceof Pair<T>) //Error
  • 不能创建参数化类型的数组
Pair<String>[] strs = new Pair<String>[10];但可以声明 Pair<String>[] 变量。
  • 不能实例化类型变量
new T(); //Errornew T[]; //ErrorT.class //Error
  • 禁止带有类型变量的静态域和方法
  • 不能抛出和捕获泛型类的实例

五. 泛型类型的继承规则

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

这里写图片描述

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

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

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

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

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

List<? super Manager> employees1 = new ArrayList<Employee>();//OKemployees1.add(new Manager());//写入List<? super Manager> employees2 = new ArrayList<Object>();//OKemployees2.add(new Manager());//写入

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

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

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

List<?> employees4 = new ArrayList<Manager>();employees4.add(new Manager());//Error
0 0
原创粉丝点击