【Java】泛型的类别

【Java】泛型的类别,第1张

今天我们不讲泛型的来龙去脉,讲讲泛型到底有哪些类别,也就是Type这个接口到底有多少不同的实现(jdk中)

大家可能会疑惑,泛型还能有多种不同的类型?

这不是我前段时间写了一个库【Java】简单优雅的加载外部 jar 中的 Class|插件化

在这个库中我需要实现一个功能:通过泛型来推导数据类型来加载对应的插件内容

于是我就对我们平时常用的泛型做了一些研究

如果大家之前有去了解过相关的内容,就会知道Type接口会有一些不同的实现(jdk中)

  • Class
  • TypeVariable
  • ParameterizedType
  • WildcardType
  • GenericArrayType

那么今天我们就来看看这些类型都对应了什么写法的泛型

Class

首先Class我们接触的比较多,虽然实现了Type接口,但不是泛型,就是普通的类的类型,并不具有泛型的一些参数属性

TypeVariable

可变类型,可以得到最原始的类型信息

如我们常用的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

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[]

ParameterizedType genericComponentType = (ParameterizedType) actualTypeArgument.getGenericComponentType();
System.out.println(genericComponentType);
//输出 java.lang.Class

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条件

上面的接口表示,这个泛型必须要实现SerializableCloneable,两个都要满足

所以比如ArrayList就是可以的:Custom

而且泛型中的条件可以有多个,但是最多只能有一个类,其他必须为接口

可以猜想是java只能继承一个父类但是可以实现多个接口的原因

那么今天的内容就是这样啦

其他的文章

【Java】简单优雅的加载外部 jar 中的 Class|插件化

【Spring Boot】一个注解实现下载接口

【拿来吧你】JDK动态代理

【Java】异步回调转为同步返回

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/869914.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存