今天我们不讲泛型的来龙去脉,讲讲泛型到底有哪些类别,也就是Type
这个接口到底有多少不同的实现(jdk中)
大家可能会疑惑,泛型还能有多种不同的类型?
这不是我前段时间写了一个库【Java】简单优雅的加载外部 jar 中的 Class|插件化
在这个库中我需要实现一个功能:通过泛型来推导数据类型来加载对应的插件内容
于是我就对我们平时常用的泛型做了一些研究
如果大家之前有去了解过相关的内容,就会知道Type
接口会有一些不同的实现(jdk中)
Class
TypeVariable
ParameterizedType
WildcardType
GenericArrayType
那么今天我们就来看看这些类型都对应了什么写法的泛型
Class首先Class
我们接触的比较多,虽然实现了Type
接口,但不是泛型,就是普通的类的类型,并不具有泛型的一些参数属性
可变类型,可以得到最原始的类型信息
如我们常用的ArrayList
我们可以通过getTypeParameters
来获得他的泛型信息
ArrayList.class.getTypeParameters();
但是我们只能拿到E
,拿不到具体的类型,毕竟实例化之后任意的类型都有可能
那么有没有能拿到具体类型的泛型呢,我们继续往下看
ParameterizedType参数化类型,可以获得<
>
中定义的具体类型
假设我们继承ArrayList
并指定泛型为String
public class StringArrayList extends ArrayList<String> {
}
这种情况下,我们就可以使用getGenericSuperclass
来获得泛型信息
StringArrayList.class.getGenericSuperclass();
调用上面的方法我们就能得到一个ParameterizedType
通过ParameterizedType#getRawType()
就可以获得ArrayList.class
通过ParameterizedType#getActualTypeArguments()
就可以获得String.class
ParameterizedType type = (ParameterizedType) StringArrayList.class.getGenericSuperclass();
Type rawType = type.getRawType();
System.out.println(rawType);
//输出 class java.util.ArrayList
Type actualTypeArgument = type.getActualTypeArguments()[0];
System.out.println(actualTypeArgument);
//输出 class java.lang.String
WildcardType
通配符类型,可以获得泛型的类型界限
主要通过? extends
或? super
约束
举个例子
public class ClassArrayList extends ArrayList<Class<? extends Serializable>> {
}
其中? extends Serializable
就是WildcardType
这里需要注意的是不带<
>
通过WildcardType#getUpperBounds()
就可以获得Serializable.class
ParameterizedType type = (ParameterizedType) ClassArrayList.class.getGenericSuperclass();
Type rawType = type.getRawType();
System.out.println(rawType);
//输出 class java.util.ArrayList
ParameterizedType actualTypeArgument = (ParameterizedType) type.getActualTypeArguments()[0];
System.out.println(actualTypeArgument);
//输出 java.lang.Class extends java.io.Serializable>
Type argumentRawType = actualTypeArgument.getRawType();
System.out.println(argumentRawType);
//输出 class java.lang.Class
WildcardType argumentActualTypeArgument = (WildcardType) actualTypeArgument.getActualTypeArguments()[0];
System.out.println(argumentActualTypeArgument);
//输出 ? extends java.io.Serializable
Type upperBound = argumentActualTypeArgument.getUpperBounds()[0];
System.out.println(upperBound);
//输出 interface java.io.Serializable
GenericArrayType
泛型数组类型,表示泛型类型的数组类型
修改一下上面的例子
public class ClassesArrayList extends ArrayList<Class<? extends Serializable>[]> {
}
实际上就是在原本的泛型类型外又包了一层
ParameterizedType type = (ParameterizedType) ClassesArrayList.class.getGenericSuperclass();
Type rawType = type.getRawType();
System.out.println(rawType);
//输出 class java.util.ArrayList
GenericArrayType actualTypeArgument = (GenericArrayType) type.getActualTypeArguments()[0];
System.out.println(actualTypeArgument);
//输出 java.lang.Class extends java.io.Serializable>[]
ParameterizedType genericComponentType = (ParameterizedType) actualTypeArgument.getGenericComponentType();
System.out.println(genericComponentType);
//输出 java.lang.Class extends java.io.Serializable>
Type argumentRawType = genericComponentType.getRawType();
System.out.println(argumentRawType);
//输出 class java.lang.Class
WildcardType argumentActualTypeArgument = (WildcardType) genericComponentType.getActualTypeArguments()[0];
System.out.println(argumentActualTypeArgument);
//输出 ? extends java.io.Serializable
Type upperBound = argumentActualTypeArgument.getUpperBounds()[0];
System.out.println(upperBound);
//输出 interface java.io.Serializable
没见过的泛型写法
接下来再说一个我在查资料时见到的一种泛型写法
public class Custom<T extends Serializable & Cloneable> {
}
不知道大家之前有没有遇到过这样的写法
然后我就研究了一下,发现这其实就是一个AND
条件
上面的接口表示,这个泛型必须要实现Serializable
和Cloneable
,两个都要满足
所以比如ArrayList
就是可以的:Custom
而且泛型中的条件可以有多个,但是最多只能有一个类,其他必须为接口
可以猜想是java
只能继承一个父类但是可以实现多个接口的原因
那么今天的内容就是这样啦
其他的文章【Java】简单优雅的加载外部 jar 中的 Class|插件化
【Spring Boot】一个注解实现下载接口
【拿来吧你】JDK动态代理
【Java】异步回调转为同步返回
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)