为什么要使用泛型?
- 避免类型转换
- 编译时的强类型检查
1.类的泛型
- 单泛型
1
2
3
| public class InfoT<T> {
private T name;
|
- 多值泛型
1
2
3
4
| public class InfoKV<K,V> {
private String name;
private K kk;
private V vv;
|
- 泛型嵌套
1
| InfoKV<InfoT<String>, Object> objectObjectInfoKV = new InfoKV<>();
|
2.接口泛型
接口泛型的定义与两种实现方式
1
2
3
| public interface InfoT<T> {
T method2();
}
|
- 子类实现接口直接明确泛型类型
1
2
3
4
5
6
7
| public class InfoA implements InfoT<Integer>{
@Override
public Integer method2() {
System.out.println("直接实现");
return 22;
}
}
|
- 实现接口的子类不明确声明泛型类型
1
2
3
4
5
6
7
8
9
10
11
12
| public class InfoB<T> implements InfoT<T> {
private T name;
public InfoB(T name) {
this.name = name;
}
@Override
public T method2() {
return name;
}
}
|
3.泛型方法
定义
1
2
3
| public <T> T func(T obj) {}
<T> 为规定泛型
T 为返回值类型
|
常见的几种泛型方法
- 普通泛型方法
1
2
3
| <T> T method1(T t){
return t;
}
|
- 返回值为 void
1
2
3
| <T> void method2(T t){
return;
}
|
- 返回值为 List 泛型
1
2
3
| <T> List<T> method3(T t){
return new ArrayList<T>();
}
|
4.泛型擦除问题
Java 泛型是使用类型擦除来实现的,使用泛型时,任何具体的类型信息都被擦除了。 即把泛型中的所有类型参数替换为 Object,泛型不会产生运行时开销。
例子
1
2
3
4
5
| ArrayList<String> list1 = new ArrayList<>();
ArrayList<Object> list2 = new ArrayList<>();
System.out.println(list1.getClass()); //class java.util.ArrayList
System.out.println(list2.getClass()); //class java.util.ArrayList
|
5.泛型的继承问题
泛型不能用于显式地引用运行时类型的操作之中,例如:转型、instanceof 操作和 new 表达式。因为所有关于参数的类型信息都丢失了。
**简单的来说就是,所有的泛型在编译通过后都会当成 List
1
2
3
| List<Integer> list = new ArrayList<>();
List<Object> list2 = list; // Erorr
|
6. 类型边界
格式 <T extends XXX>
实现一个比较大小的方法 static <T extends Comparable<T>> T max(T x, T y, T z)
x,y,z 三者都必须是实现Comparable接口的数据类型。
类型边界可以设置多个 <T extends B1 & B2 & B3>
extends 关键字后面的第一个类型参数可以是类或接口,其他类型参数只能是接口