## 1 泛型的作用

* 适用于多种数据类型执行相同的代码。
* 泛型中的类型在使用时指定，不需要强制类型转换(出现异常 java.lang.ClassCastException)。

## 2 泛型类和泛型接口

泛型：参数化类型，将类型由原来的具体的类型参数化，类似于方法中的变量参数，此时类型也定义成参数形式（可以称之为类型形参），然后在使用/调用时传入具体的类型（类型实参）。

```java
//泛型类
public class NormalGeneric<T> {
    private T data;

    public NormalGeneric(T data) {
        this.data = data;
    }
}

//泛型接口
public interface IGenerator<T> {
    T getData();
}
//1.实现泛型接口方式
public class ImplGenerator1<T> implements IGenerator<T> 

//2.实现泛型接口方式
public class ImplGenerator2 implements IGenerator<String> 
```

## 3 泛型方法

可以在任何地方定义，普通类、泛型类等。

```java
public class GeneratorMethod {
    public <T> T getMethod(T... a) { //使用 <T>
        return a[a.length / 2];
    }

    public static void main(String[] args) {
        GeneratorMethod generatorMethod = new GeneratorMethod();
        String s = generatorMethod.getMethod("Java", "C++");
        System.out.println(s);
    }
}

public class NoGeneratorMethod<T> {
    private T key;
    public NoGeneratorMethod(T key){
        this.key = key;
    }
    
    public T getKey() { //注意：不是泛型方法
        return key;
    }
}   

```

## 4 限定类型变量

对类型变量进行约束,，可以在泛型类、泛型接口、泛型方法上世使用。

```java
public <T extends Comparable> T max(T a, T b) {
      return a.compareTo(b) > 0 ? a : b;
}

//extends左右都允许有多个，如 T,V extends Comparable & Serializable
//但是只允许有一个类，且必须在列表第一个位置
public <T extends Comparable & Serializable> T min(T a, T b) {
      return a.compareTo(b) > 0 ? b : a;
}
```

## 5 注意

```java
//不能使用类型变量
public static  T instance;

//基本数据类型不支持
NormalGeneric<int> a = new NormalGeneric<>();//出错

//创建数组不支持
NormalGeneric<Integer>[] a = new NormalGeneric<>[9];//出错

//不能实例化类型变量
this.data = new T();

//不能 extends Exception、Throwable，不能捕获泛型类实例 
public static class MyException<T> extends Exception {
     public <T extends Throwable> void doWork(T t) {
           try {

           } catch (T e) {
                
           }
     }
    
    public <T extends Throwable> void doWork1(T t) throws T{
           try {

           } catch (Throwable e) {
                throw e;//可以抛出泛型异常
           }
     }
}
```

## 6 通配符类型

```java
public class Fruit {}

public class Apple extends Fruit {}

public class Banana extends Fruit {}

public class GreenBanana extends Banana {}

public class GenericType<T> {
    private T data;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

```

### 6.1  ? extends X

表示类型的上界，类型参数是 X 的子类。

```java
public static void main(String[] args) {
        GenericType<Fruit> a = new GenericType<>();
        GenericType<? extends Fruit> b = new GenericType<>();
        GenericType<Apple> c = new GenericType<>();

        a = c; //出错 
        b = c; //可以 <? extends Fruit> 表示上界是 Fruit ,子类当然可以。
        Apple apple = new Apple();
        Banana banana = new Banana();
        b.setData(apple);//出错 上限：set 不可
        b.setData(banana);//出错 
        Fruit fruit = b.getData();//可以，上限：get 可行
}
```

### 6.2 ? super X

表示类型的下界，类型参数是 X 的超类

```java
 public static void main(String[] args) {   
       GenericType<? super Banana> a = new GenericType<>();
       GenericType<GreenBanana> b = new GenericType<>();
       GenericType<Fruit> c = new GenericType<>();
       a = b;//出错
       a = c;//可以 <? super Banana> 表示下界是 Banana ,他的超类当然可以
     
       Banana banana = new Banana();
       GreenBanana greenBanana = new GreenBanana();
       Fruit fruit = new Fruit();
       a.setData(banana);//可以
       a.setData(greenBanana);//可以
       a.setData(fruit);//出错 <? super Banana> 表示下界是 Banana，Fruit 超了，强记
       Object data = a.getData();//唯一取值是 Object
}
```

### 6.3 无限定的通配符 ？

表示对类型没有什么限制，可以把 ？看成所有类型的父类，如Pair< ?>；

比如：

ArrayList<T> al=new ArrayList<T>(); 指定集合元素只能是T类型

ArrayList<?> al=new ArrayList<?>();集合元素可以是任意类型，这种没有意义，一般是方法中，只是为了说明用法。

在使用上：

？ getFirst() ： 返回值只能赋给 Object，；

void setFirst(?) ： setFirst 方法不能被调用， 甚至不能用 Object 调用；

## 7 虚拟机实现泛型

类型擦除，Java 泛型是伪泛型，仅仅是对方法的 Code 属性中的字节码进行擦除，实际上元数据中还是保留了泛型信息，能通过反射手段取得参数化类型，使用 Signature 存储一个方法在字节码层面的特征签名（泛型类型）。