java-泛型

泛型

  泛型是指参数化类型的能力,可以定义带泛型类型的类或者方法,随后编译器会用具体的类型来替换它。

  使用泛型的优点是能够在编译时而不是在运行时检测出错误。泛型类或者方法允许用户指定可以和这些类或者方法一起工作的对象类型,如果试图使用一个不相容的对象,编译器就会检测出这个错误。

 

    public interface Comparable<T> {
        public int compareTo(T o);
    }

 

这里的<T>表示泛型类型,随后可以用一个实际具体类型来替换它。替换泛型类型称为泛型实例化。按照惯例像E,T这样的单个大写字母用于表示一个泛型类型。

 

在JDK1.5之前还不支持泛型的时候,都是靠Object类型来控制参数的传递。拿ArrayList举例来说:

JDK1.5之前:add(o:Object)。

JDK1.5之后:add(o: E)。

可以通过对E的泛型实例化来规定入参的类型,这样就可以再编译的时候直接检测类型是否匹配,而不是像早期的Object 做类型转换的时候才能知晓类型是否匹配。

 

需要注意的是当使用new ArrayList<String>(); 创建对象时,并是不表示其构造方法也是 public ArrayList<String>(){}。

其构造方法还是public ArrayList(){}。

 

将泛型指定为另外一种类型,这样的泛型类型称之为受限通配泛型。

public class Num<E extends Number>{}

表示E泛型类型只接收Number类及其子类类型。

 

public class Num<?>{}

 ?表示非受限通配泛型,它与<E extends Object>功能一致。

 

public class Num<? super Integer>{}

?表示Integer的父类。

 

T 和?的区别:

Class<T>在实例化的时候,T要替换成具体类
Class<?>它是个通配泛型,?可以代表任何类型,主要用于声明时的限制情况

 

需要注意的是,泛型在运行的时候会被消除,转换成具体的类型。所以加载到JVM中的还是一个类型。

ArrayList<Integer> list1 = new ArrayList<Integer>();

ArrayList<String> list2 = new ArrayList<String>();

虽然在编译时期定义的是2个类,但是一旦运行项目,加载到JVM中的智勇一个ArrayList

所以list1 instanceof ArrayList 和list2 instanceof ArrayList 都是true,而且不能写成list1 instanceof ArrayList<String>

因为在JVM中并没有ArrayList<String>这个类。

 

不能直接创建泛型实例 New E();

不能使用泛型类型来创建数组 New E[];

不能在静态环境下使用泛型类:

  因为在运行时期,泛型类对于JVM来说其实都是想同的类,静态变量或者静态方法是被所有的实例所共享的,那么这个时候如果使用静态泛型就会出现重复的类型 导致无法识别。

异常类不能是泛型的:

  泛型类不能扩展java.lang.Throwable,因此,下面的类声明是非法的:

  为什么?如果允许这么做,就应为MyException<T>添加一个catch子句,如下所示:

  public class MyException<T> extends Exception {

  }

  JVM必须检查这个从try子句中抛出的异常以确定它是否与catch子句中指定的类型匹配。但这是不可能的,因为在运行时类型信息是不出现的。

  try {

  }

  catch (MyException<T> ex) {

  }

posted @ 2019-01-15 10:24  粗鲁师太  阅读(175)  评论(0编辑  收藏  举报