1.泛型是什么
Java的泛型是一种伪泛型,只存在于编译期不存在于JVM运行期。它的JDK5引入的一种参数化类型。
2.使用泛型的好处
- 将运行期可能出现的错误提前到编译期判断(只要编译期没有警告运行期就不会出现问题),提升代码的健壮性。
- 使代码更简洁(不需要进行类型强转)
//不使用泛型 RawPlate rawPlate = new RawPlate(); rawPlate.set(new Apple()); Banana bannana = (Banana) rawPlate.get(); //使用了泛型 AiPlate<Banana> aiPlate = new AiPlate<>(); aiPlate.set(new Apple()); aiPlate.set(new Banana()); Banana b = aiPlate.get();
- 提升代码的复用
int[] ints = new int[10]; sort(ints); double[] doubles = new double[10]; sort(doubles); Object[] objects = new Object[10]; sort(objects); public static void sort(int[] array){} public static void sort(double[] array){} public static <T> void sort(T[] array){}>
3.泛型有哪几种:
- 泛型类 :
class Plate <T>
class AiPlate<T> extends Plate<T> - 泛型接口
interface Plate<T>
- 泛型方法
public <T> T getData(T t){return t; }
4.泛型的继承原则:
遵循类的单继承 接口的多继承原则,在继承关系中 类写在第一位,接口跟在后面 用&连接,只要继承原则中原始的T不变,类的继承关系就存在
```
public class A< T extends ClassA & IB & IC & ID >{};
class A<T>
class B<T> extends A<T>
class C<K,T> extends B<T>
```
5.泛型的擦除原则:
1.擦除时会擦除到第一层限制关系 如果没有则擦除成Object:
如 Class <T extends Comparable<T>>
2.生成桥方法是为了保持多态性
- Type类型会保留在常量池里
补充数组协变:
如 class Apple extends Fruilt那么 Apple[] 也会是 Fruit[]的子类
6.泛型的限定符 、通配符<?>与PECS原则(Producer extends Consumer super)
```
class A<T extends Fruit> 只能取 ,生产者
class B<T super Food> 只能放,消费者
class C<?>
```
public class Test1 {
public static void main(String[] args) {
//限定类型
List<Apple> src = new ArrayList<>(10);
src.add(new Apple(1));
List<Apple> dest = new ArrayList<>(10);
dest.add(new Apple(2));
System.out.println(dest);
copy(dest,src);
System.out.println(dest);
//更换泛型
List<Banana> src2 = new ArrayList<>(10);
src2.add(new Banana(1));
List<Banana> dest2 = new ArrayList<>(10);
dest2.add(new Banana(2));
System.out.println(dest2);
//调用copy 发现方法无法调用
//copy(dest2,src2);
copy2(dest2,src2);
System.out.println(dest2);
//使用父类型作为泛型
List<Banana> src3 = new ArrayList<>(10);
src3.add(new Banana(1));
List<Fruit> dest3 = new ArrayList<>(10);
dest2.add(new Banana());
// Test1.<Banana>copy2(dest3,src3);
//这里 dest3的泛型是Fruit 泛型方法的泛型是Banana src的泛型是Banana copy3 dest3 ? super T 表述 fruit super banana
Test1.<Banana>copy3(dest3,src3);
List<Fruit> dest4 = new ArrayList<>(10);
dest4.add(new Banana());
//这里 dest4的泛型是Fruit 泛型方法的泛型是Banana src的泛型是Banana copy3
// dest4 ? super T 表述 fruit super banana
// src3? extends T 表述为 Banana extends Fruit
Test1.<Fruit>copy4(dest4,src3);
}
/**
* 限定只能传入Apple
* @param dest 目标 存入
* @param src 源数据 取出
* 从src取出一个apple ->dest
*/
public static void copy(List<Apple> dest,List<Apple> src){
Collections.copy(dest,src);
}
/**
* 限定同个T在调用时确定 但是都是同个类型
* @param dest List<Fruit>
* @param src List<Banana>
* @param <T>
* 从src取出一个apple ->dest
*/
public static <T> void copy2(List<T> dest,List<T> src){
Collections.copy(dest,src);
}
/**
* 限定上界
* @param dest List<? super T> 限定存入 消费者的泛型 必须是 实际类型的父类
* @param src List<T> src
* @param <T>
* 泛型是Fruit banana ->fruit的子类
*/
public static <T> void copy3(List<? super T> dest,List<T> src){
Collections.copy(dest,src);
}
/**
*
* @param dest List<? super T> 限定存入 消费者的泛型 必须是 实际类型的父类
* @param src List<? extends T> 限定取出 生产者的泛型 必须是 实际类型的子类
* @param <T> 实际方法的泛型
*/
public static <T> void copy4(List<? super T> dest,List<? extends T> src){
Collections.copy(dest,src);
}
}
作业:
说出一下类型的区别
Plate:没有使用泛型的Plate类 class Plate{}
Plate p = new Plate();
Plate<Object>: 泛型为Object的Plate类
class Plate<Object>{} Plate p = new Plate<Object>();
Plate<?>: 通配的一个Plate类 class Plate<?>{}
Plate p = new Plate<Apple>(), Plate p2 = new Plate<Object>();
Plate<T>:泛型类型为T的类 class Plate<T>
Plate p = new Plate<Apple>(),
Plate<? extends T> 继承 T 的通配Plate 类 class Plate<? extends T>{} 假设 T为Fruit Apple Banana为Fruit的子类
Plate p = new Plate<Apple>(), Plate p2 = new Plate<Banana>(),
Plate<? super T> 父类为 T 的通配Plate 类 class <? super T>{} 假设T为Food Fruit为Food的子类 Apple Banana为Fruit的子类
Plate p = new Plate<Apple>(), Plate p2 = new Plate<Banana>(),
网友评论