一、泛型
1. 什么是泛型?
- Java泛型 generics 是JDK5中引入的 一种参数化
2. 为什么使用泛型,使用它的好处?
- 更健壮(只要编译器没有警告,那么运行期就不会出现ClassCastException)
- 更简洁,不用类型强转
- 更灵活,复用
// List.java 中排序对泛型的使用
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}
参数类型化
把数据当参数一样传递
<数据类型>只能是引用类型(泛型的副作用)
比如:
- Plate<T>中的”T“成为类型参数
- Plate<Apple>中的”Apple“成为实际类型参数
- ”Plate<T>“ 整个成为泛型类型
- ”Plate<Apple>“整个称为参数化的类型 ParameterizedType
泛型类的本质
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jVup81wG-1592823093440)(https://chitanda-blog.oss-cn-beijing.aliyuncs.com/img/image-20200620234539735.png)]
运行结果为true,由此可见运行时获取的类信息是完全一致的,泛型类型被擦除了,只留下原始类型——ArrayList
类型擦除-Type Erasure
Java语言引入了泛型,以在编译时提供更严格的类型检查并支持泛型编程。 为了实现泛型,Java编译器将类型擦除应用于:
- 如果类型参数不受限制,则将通用类型中的所有类型参数替换为其边界(上下限)或 Object 。因
此,产生的字节码仅包含普通的类,接口和方法。 - 必要时插入类型转换,以保持类型安全。
- 生成桥接方法以在扩展的泛型类型中保留多态。
类型擦除可确保不会为参数化类型创建新的类;因此,泛型不会产生运行时开销。
泛型类型的擦除-Erasure of Generic Types
在类型擦除过程中,Java编译器将擦除所有类型参数,如果类型参数是有界的,则将每个参数替换为其第一个边界;如果类型参数是无界的,则将其替换为 Object:
class A<T> {
private T data;
public A(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
通过查看A.class以及字节码可发现Java编译器将参数类型T替换为Object:
B类使用限定类型参数:
public class B<T extends Comparable<T>> {
private T data;
public B(T data) {
this.data = data;
}
public T getData() {
return data;
}
}
Java编译器将绑定类型参数T替换为第一个绑定类 Comparable:
桥接方法
在编译扩展参数化类或实现参数化接口的类或接口时,作为类型擦除过程的一部分,Java编译器可能需要创建一个称为桥接方法的综合方法.
举个例子:
interface Box<T> {
void set(T t);
}
class MyBox<T extends Comparable<T>