概述
在JDK1.5之前只有原始类型,此时所有的原始类型都通过字节码文件类Class进行抽象。Class类的一个具体对象就代表一个指定的原始类型。
JDK1.5加入了泛型类,扩充了数据类型,从只有原始类型基础上扩充了参数化类型、类型变量类型、通配符类型、泛型数组类型。Type是Java语言中所有类型(Class)的公共父接口。
Type类关系图
从左到右依次是:
- Class(原始/基本类型):不仅包括我们平常所指的类、枚举、数组、注解,还包括基本类型int、float等等。
- TypeVariable(类型变量):比如List中的T等。
- WildcardType(通配符类型):也叫做泛型表达式类型,例如List<? extends Number>这种。
- ParameterizedType(参数化类型):就是我们平常所用到的泛型List、Map(注意和TypeVariable的区别,参数化类型表示的是List这样的一个整体而不是T)。
- GenericArrayType(泛型数组类型):并不是我们工作中所使用的数组String[]、Byte[](这些都是Class),而是到带有泛型的数组,即T[]。
Type接口本身算是一个标记接口,不提供任何需要复写的方法。
TypeVariable类型变量
泛型信息在编译时会被转换成一个特定的类型,而TypeVariable就是用来反应JVM编辑该泛型前的信息。(通俗的讲,TypeVariable就是我们常用的List<T>、Map<K,V>
中的T,K这种泛型变量)。
还可以对类型变量加上extends限定,这样会有类型变量对应的上限;值的注意的是,类型变量的上限可以有多个,必须使用&连接,例如:List<T extends Number & Serializable>,其中&后必须是接口。
1)TypeVariable源码:
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
// 类型变量对应的上边界,如果没有指定上限,返回Object 可以有多个
Type[] getBounds();
// 获取类型变量所在类的Type,比如TypeVariableTest<T>类,getGenericDeclaration()得到的就是TypeVariableTest。
D getGenericDeclaration();
// 获取类型变量在源码中定义的名称
String getName();
// JDK8新增的,获取注解类型的上限数组
AnnotatedType[] getAnnotatedBounds();
}
2)具体用法:
public class TypeVariableTest<K extends Number, T> {
// K有指定上边界 Number
private K key;
// T没有指定上边界,其默认上边界为Object
private T value;
public static void main(String[] args) {
TypeVariable<Class<TypeVariableTest>>[] typeParameters = TypeVariableTest.class.getTypeParameters();
for (TypeVariable<Class<TypeVariableTest>> type : typeParameters) {
int index = type.getBounds().length - 1;
// 输出上边界
System.out.println("---getBounds()-- " + type.getBounds()[index]);
// 输出名称
System.out.println("---getName()-- " + type.getName());
// 输出所在的类的类型
System.out.println("---getGenericDeclaration()-- " + type.getGenericDeclaration());
}
}
}
3)输出结果:
---getBounds()-- class java.lang.Number
---getName()-- K
---getGenericDeclaration()-- class com.study.concurrentprogramming.genericiy.TypeVariableTest
---getBounds()-- class java.lang.Object
---getName()-- T
---getGenericDeclaration()-- class com.study.concurrentprogramming.genericiy.TypeVariableTest
WildCardType通配符类型
表示通配符类型,比如<?>,<? extends Number>等
如果没有指定的上边界,则默认Object,如果没有指定下边界,则默认为String。
1)WildCardType源码:
public interface WildcardType extends Type {
// 获得泛型表达式上边界,表达式中使用extends
Type[] getUpperBounds();
// 或者泛型表达式的下边界,表达式中使用super
Type[] getLowerBounds();
}
2)具体用法:
public class WildcardTypeTest {
// 使用通配符类型参数的方法
public void testWildcardType(
List<? extends OutputStream> outputStreams,
List<? super InputStream> inputStreams,
List<Integer> list, InputStream inputStream) {
}
public static void main(String[] args) {
// 获取WildcardTypeTest类的所有方法(本例中是testWildcardType方法)
Method[] declaredMethods = WildcardTypeTest.class.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println("method name: " + method.getName());
// 获取方法的所有参数类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
for (Type type : genericParameterTypes) {
System.out.println("type: " + type.toString());
// 如果不是参数化类型则直接continue
if (!(type instanceof ParameterizedType)) {
continue;
}
// 将当前类型强转为参数化类型并获取实际参数(即含有通配符的泛型类型)
Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];
// 输出其是否为通配符类型
System.out.println("type instanceof WildcardType: "
+ (actualTypeArgument instanceof WildcardType));
if (actualTypeArgument instanceof WildcardType) {
int lowIndex = ((WildcardType) actualTypeArgument).getLowerBounds().length - 1;
int upperIndex = ((WildcardType) actualTypeArgument).getUpperBounds().length - 1;
// 输出上边界与下边界
System.out.println("getLowerBounds(): " +
(lowIndex >= 0 ? ((WildcardType) actualTypeArgument).getLowerBounds()[lowIndex] : "String")
+ ";getUpperBounds(): " +
(upperIndex >= 0 ? ((WildcardType) actualTypeArgument).getUpperBounds()[upperIndex] : "Object"));
}
}
}
}
}
3)输出结果:
method name: main
type: class [Ljava.lang.String;
method name: testWildcardType
type: java.util.List<? extends java.io.OutputStream>
type instanceof WildcardType: true
getLowerBounds(): String;getUpperBounds(): class java.io.OutputStream
type: java.util.List<? super java.io.InputStream>
type instanceof WildcardType: true
getLowerBounds(): class java.io.InputStream;getUpperBounds(): class java.lang.Object
type: java.util.List<java.lang.Integer>
type instanceof WildcardType: false
type: class java.io.InputStream
//后面待更新…