15.2 简单泛型

在没有泛型之前,采用的是继承机制来实现泛型,但是需要强制类型转换,会有风险

创建泛型类:

  1. public class A<T>{
  2. T ...
  3. ...
  4. }
  5. //创建泛型对象
  6. A<..> a = new A<>();

15.2.1 使用泛型创建多维元祖,实现一次调用返回多个对象

  1. public class Tuple<A,B,C,...>{//A,B,C是泛型
  2. public final A first;
  3. public final B second; // 使用final使得客户端程序员无法修改,相当于private+getset方法
  4. ...
  5. public Tuple(A a,B b){first = a;second = b;} //构造器
  6. }

15.3 泛型接口

public interface Generator<T> {T next();}

实现接口:

  1. public class A implements Generator<Integer>{ //指定泛型T具体类型,可以是包装类数据类型也可以是自定义类
  2. @Override
  3. public Integer next(){ // 重写接口中的方法
  4. ...
  5. }
  6. }

15.4 泛型方法

为什么要用泛型方法?

  • 因为泛型类要在实例化的时候就指明类型,如果想换一种类型,不得不重新new一次,可能不够灵活;而泛型方法可以在调用的时候指明类型,更加灵活
  • 使用泛型类,创建对象时必须指定泛型具体类型;而使用泛型方法,则不必指定,编译器会根据参数自动判断

    泛型方法定义

    泛型参数列表必须置于返回值之前前,泛型方法的类可以是泛型类也可以不是
    • public <T> void f(T x){...}
    • public <T,E> E f(T a, E b) {...}
    • public static <T> T f(T a){} //泛型静态方法定义

显式指定类型调用泛型方法

  1. public class A{
  2. public <T> void fun(T x){//泛型方法
  3. ...
  4. }
  5. public static <T> void staticfun(T x){ //静态泛型方法
  6. ...
  7. }
  8. public void main{
  9. A<Integer> a = new A<>();
  10. a.<String>fun("abc"); //指定泛型具体类型调用泛型方法
  11. A.<String>staticfun("abc"); //指定泛型具体类型调用静态泛型方法
  12. }
  13. }

15.7 擦除

什么是擦除:

  • 泛型具体类型不同擦除后会变成原生类 如List 和List是一种类型,最后都会擦除成List
  • 泛型**只是用来检查类型正确性,一旦运行就会被擦除**

    擦除的结果:

  • **List<T>**被擦除为**List**

  • **List<String>**被擦除为**List<Object>**
  • **<T extends A>** 擦除为 **<A>**

    什么是边界:

  • 运行后泛型会被擦除到上边界

  • class A<T extends B> 擦除到