Java 泛型相关知识
2023-12-14 00:58:12
什么是泛型?
Java 泛型(generics)是JDK5中引入的一种参数化类型特性。
为什么使用泛型,使用泛型的好处?
- 代码更健壮(只要编译期没有警告,那么运行期就不会出现
ClassCastException
) - 代码更简洁(不用强转)
- 代码更灵活,复用
什么是参数化类型:
- 把类型当参数一样传递
- <数据类型> 只能是引用类型(泛型的副作用)
举个例子:
public interface Plate<T> {
public void set(T t);
public T get();
}
public class ATPlate<T> implements Plate<T> {
private List<T> items = new ArrayList<T>(10);
public <T> ATPlate<T> getATPlate() {
return new ATPlate<T>();
}
}
Plate<T>
中的 "T
” 称为类型参数,Plate<T>
整个称为泛型类型Plate<Banana>
中的 “Banana
” 称为实际类型参数,Plate<Banana>
整个称为参数化的类型ParameterizedType
泛型其实就是在类上面传参,可以类比方法传参,只不过类上面传的参数类型也只能是类。
泛型类型可以通过extends
指定多个限定类型。
什么是多个限定类型,例如:
class A {
}
interface B {
}
interface C {
}
// 具有多个限定的类型变量是范围中列出的所有类型的子类型。如果范围之一是类,则必须首先声明类
class D<T extends B & A & C> {
} // 编译报错
class D<T extends A & B & C> {
} // 编译OK
泛型擦除
Q:Java 泛型的原理?什么是泛型擦除机制?
- Java 的泛型是 JDK5 引入的特性,为了向下兼容,虚拟机其实是不支持泛型,所以 Java 实现的是一种伪泛型机制,也就是说 Java 在编译期擦除了所有的泛型信息,这样 Java 就不需要产生新的类型到字节码,所有的泛型类型最终都是一种原始类型,在 Java 运行时根本就不存在泛型信息。
Q:Java 编译器具体是如何擦除泛型的?
- 检查泛型类型,获取目标类型
- 擦除类型变量,并替换为限定类型
- 如果泛型类型的类型变量没有限定(
<T>
),则用Object
作为原始类型 - 如果有限定(
<T extends XCIass>
),则用XCIass
作为原始类型 - 如果有多个限定(
T extends XCIass1 & XCIass2
),则使用第一个边界XCIass1
作为原始类型
- 如果泛型类型的类型变量没有限定(
- 在必要时插入类型转换以保持类型安全
- 生成桥方法以在扩展时保持多态性
例如,只有一个泛型 T
擦除后只有一个 Object
对象:
Basket<Fruit>
不存在于编译后的字节码
如果泛型有多个继承限定类型,则使用第一个限定类作为擦除后的类型,此外如果泛型类继承了支持泛型的接口,还会生成桥方法:
如何通过反射获取泛型参数
泛型虽然被擦除了,但是在 类常量池 里面其实保留了泛型信息,所以可以通过反射获取泛型的信息 getGenericType()
Java 的泛型擦除并不是将所有泛型信息全部都擦除了,会将类上和方法上声明的泛型信息保存在字节码中的 Signature
属性中,这也是反射能够获取泛型的原因。但是在方法中的泛型信息是完全擦除了。
public class HelloWorld {
Map<String, String> map;
public static void main(String[] args){
try {
Field field = HelloWorld.class.getDeclaredField("map");
Type type = field.getGenericType();
System.out.println(type);// java.util.Map<java.lang.String, java.lang.String>
System.out.println(type instanceof ParameterizedType); // true
ParameterizedType pType = (ParameterizedType) type;
System.out.print1n(pType.getRawType());// interface java.util.Map
for (Type argType : pType.getActualTypeArguments()) {
System.out.println(argType); // class java.lang.String
}
System.out.println(pType.getOwnerType()); // null
Method method =HelloWorld.class.getMethod("applyMethod",Map.Entry.class);
Type[] types = method.getGenericParameterTypes();
ParameterizedType pTypel = (ParameterizedType) types[0];
System.out.println(pTypel.getOwnerType()); // interface java.util.Map
Map<String,String>[] maps = new Map[10];
List<?>[] lists = new List
文章来源:https://blog.csdn.net/lyabc123456/article/details/134896174
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!