• 泛型就是定义一种模板,然后在代码中为用到的类创建对应的类型。编译器会自动进行类型检查
    • 泛型如果不指定类型,那就默认是Object类型,此时使用泛型就需要进行强制转换。如List list = new ArrayList(); list.add("Hello"); list.add("World"); Stringfirst = (String) list.get(0);
  • 同一种T的子类泛型可以上转型为父类类型,如ArrayList<Integer>List<Integer>
    • 但是不能子类T转父类T,如List<Integer>List<Number>
    • 无法转换会报ClassCastException异常
  • 一个泛型运用可以有多个不同的通配符,表示是多种类型。Map<T,V>
  • 泛型必须是引用类型,因为Object无法与基本类型进行转换
  • 泛型语法:如List<Number> list = new ArrayList<Number>();
    • 前面指明了,所以后面编译器可以推断出类型,所以后面尖括号的Number可以省略 ...=new ArrayList<>();
  • 泛型有三种运用:
    • 泛型类和接口,抽象类等等类名接口名后面都要加上。返回值为类类型也是
    • 泛型方法:泛型方法特指静态的泛型方法,非静态泛型方法定义在泛型类中
    • 泛型接口
    • 泛型类

      泛型通配符

泛型接口

  • 定义一个泛型接口:**public interface Comparable<T> { int compareTo(T o); }**
  • 要使用泛型接口,毫无疑问需要实现接口。

    • 实现泛型接口很简单,只需要实现时指定一下类型即可 class Person implements Comparable<Person> {... int compareTo(Person p) ...}

      泛型类

  • 编写泛型类可以先假设为某种类型进行编写,最后将假设的类型关键字都替换为T即可

    • 如下代码将String替换为T即可
    • 然后类名后加上<T> ```java public class Pair { private String first; private String last; public Pair(String first, String last) { this.first = first; this.last = last; } public String getFirst() { return first; } public String getLast() { return last; } }
  1. <a name="ipMDy"></a>
  2. # 泛型方法(静态)
  3. - **泛型方法特指静态的泛型方法。非静态泛型方法定义在泛型类中,属于泛型类**
  4. - 假如在泛型类中编写泛型方法,则泛型方法的通配符不能跟泛型类的通配符相同
  5. - 同时还必须在static关键字后面增加一个带尖括号的通配符
  6. ```java
  7. public class Pair<T> {
  8. private T first;
  9. private T last;
  10. public Pair(T first, T last) {
  11. this.first = first;
  12. this.last = last;
  13. }
  14. public T getFirst() { ... }
  15. public T getLast() { ... }
  16. // 静态泛型方法应该使用其他类型区分:
  17. public static <K> Pair<K> create(K first, K last) { //增加了一个<K>
  18. return new Pair<K>(first, last);
  19. }
  20. }

泛型原理-擦拭法

  • Java编译器将所有泛型都视为Object类型,然后在编译时根据用户给定的类型对其进行安全的类型转换。
    • **List <Double>list=...; list.size();**经过转换后(Double)list.size()

擦拭法的局限:

  1. 不能是基本类型因为实际类型是Object,Object类型无法转为基本类型
  2. 无法取得带泛型的Class
    1. 比如说一个类class Pair<T>无论T是什么类型,getClass()获得到的都是Pair对象的类,即得到的都是**Pair**
  3. 无法判断带泛型的类型,原因同2
    1. 比如说if (list instanceof List<Double>) {} //直接报错 因为根本不存在List<Double>类型 只有List类型
  4. 构造方法不能实例化**T**类型(因为构造方法内部无法从T拿到class)
    1. 想要实例化T类型,必须借助额外的Class参数。使用时,也需要传入Class参数(即传入一个具体Class类型的参数) ```java public class Pair { private T first; private T last; public Pair() { // Compile error: first = new T(); last = new T(); } } 上述代码无法通过编译,因为构造方法的两行语句:

first = new T(); last = new T(); 擦拭后实际上变成了:

first = new Object(); last = new Object(); 这样一来,创建new Pair()和创建new Pair()就全部成了Object,显然编译器要阻止这种类型不对的代码。

#

借助Class实例化 public Pair(Class clas) { …. } //class是关键字不能作标识符 Pair pair = new Pair<>(String.class);

``` [

](https://www.liaoxuefeng.com/wiki/1252599548343744/1265104600263968)