Java中的类型(Type)体系的一些思考
Java 编程语言从Java 5以后就引入Type体系,应该是为了加入泛型而引入的。
Java Type 体系,始于Type接口,其是Java编程语言中所有类型的父接口,是对Java编程语言类型的一个抽象,源码如下所示:
public interface Type {
//返回这个类型的描述,包括此类型的参数描述。
default String getTypeName() {
return toString();
}
}
子接口:
TypeVariable- 类型变量Parameterizedtype- 参数化类型GenericArrayType- 数组类型WildcardType- 通配符类型
实现类:
Class
TypeVariable
类型变量,例如
List<T>中的T,Map<K,V>中的K和V,再比如类class TypeTest<T, V extends Object & Serializable>中的T和V。
此接口源码如下:
interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
//返回此类型参数的上界列表,如果没有上界则放回Object.
//例如 V extends Object & Serializable 这个类型参数,有两个上界,Object 和 Serializable
Type[] getBounds();
//类型参数声明时的载体
//例如 `class TypeTest<T, V extends Object & Serializable>` ,那么V 的载体就是TypeTest
D getGenericDeclaration();
String getName();
//Java 1.8加入 AnnotatedType
//如果这个这个泛型参数类型的上界用注解标记了,我们可以通过它拿到相应的注解
AnnotatedType[] getAnnotatedBounds();
}
测试代码:
public class TypeVariableDemo {
@Deprecated
abstract class A<K extends String & Serializable, V extends Object & Serializable> implements Map<K, V> {}
public static void main(String[] args) {
TypeVariable<Class<A>>[] typeParameters = A.class.getTypeParameters();
assert 2 == typeParameters.length;
// name0 是 K,上界是:String 和 Serializable
String name0 = typeParameters[0].getName();
assert "K".equals(name0);
Type[] bound0s = typeParameters[0].getBounds();
assert "String".equals(bound0s[0].getTypeName());
assert "Serializable".equals(bound0s[1].getTypeName());
// name0 的载体(genericDeclaration)是 A.class
assert TypeVariableDemo.A.class.equals(typeParameters[0].getGenericDeclaration());
// name0 绑定注解是 @Deprecated
assert Deprecated.class.equals(typeParameters[0].getBounds()[0]);
// name1 是 V,上界是:Object 和 Serializable
String name1 = typeParameters[0].getName();
assert "V".equals(name1);
Type[] bound1s = typeParameters[1].getBounds();
assert "Object".equals(bound1s[0].getTypeName());
assert "Serializable".equals(bound1s[1].getTypeName());
// name1 的载体(genericDeclaration)是 A.class
assert TypeVariableDemo.A.class.equals(typeParameters[1].getGenericDeclaration());
// name1 绑定注解是 @Deprecated
assert Deprecated.class.equals(typeParameters[1].getBounds()[0]);
}
}
ParameterizedType
参数化类型,即带参数的类型,也可以说带
<>的类型。例如List<String>,User<T>等。
其源码如下:
interface ParameterizedType extends Type {
// 获取参数类型<>里面的那些值
// 例如Map<K,V> 那么就得到[K,V]的一个数组
Type[] getActualTypeArguments();
// 获取参数类型<>前面的值
// 例如例如Map<K,V> 那么就得到 Map
Type getRawType();
// 获取内部类所在类的类型
// 例如Map有一个内部类Entry, 那么在Map.Entry<K,V>上调用这个方法就可以获得Map
Type getOwnerType();
}
测试代码:
public class ParameterizedTypeDemo {
interface A<K extends String, V extends Object> extends Map<K, V> {
abstract class AEntity<K extends String, V extends Object> implements Map.Entry<K, V> {}
}
abstract class ChildA<K extends String, V extends Object> implements A<K, V>, Map<K, V> {}
public static void main(String[] args) {
List<ParameterizedType> parameterizedTypes = Arrays.stream(A.class.getGenericInterfaces())
.filter(type -> type instanceof ParameterizedType)
.map(ParameterizedType.class::cast)
.collect(Collectors.toList());
// parameterizedTypes --> [Map]
assert 1 == parameterizedTypes.size();
Type ownerType0 = parameterizedTypes.get(0).getOwnerType();
assert ownerType0 == null;
Type rawType0 = parameterizedTypes.get(0).getRawType();
assert Map.class.equals(rawType0);
Type[] actualTypeArguments0 = parameterizedTypes.get(0).getActualTypeArguments();
assert "K".equals(actualTypeArguments0[0].getTypeName());
assert "V".equals(actualTypeArguments0[1].getTypeName());
List<ParameterizedType> parameterizedTypes1 = Arrays.stream(A.AEntity.class.getGenericInterfaces())
.filter(type -> type instanceof ParameterizedType)
.map(ParameterizedType.class::cast)
.collect(Collectors.toList());
// parameterizedTypes --> [Map.Entry]
assert 1 == parameterizedTypes1.size();
Type ownerType1 = parameterizedTypes1.get(0).getOwnerType();
// 内部类所在类是 Map
assert Map.class.equals(ownerType1);
Type rawType1 = parameterizedTypes1.get(0).getRawType();
assert Map.Entry.class.equals(rawType1);
Type[] actualTypeArguments1 = parameterizedTypes1.get(0).getActualTypeArguments();
assert "K".equals(actualTypeArguments1[0].getTypeName());
assert "V".equals(actualTypeArguments1[1].getTypeName());
List<ParameterizedType> parameterizedTypes2 = Arrays.stream(ChildA.class.getGenericInterfaces())
.filter(type -> type instanceof ParameterizedType)
.map(ParameterizedType.class::cast)
.collect(Collectors.toList());
// parameterizedTypes --> [A, Map]
assert 2 == parameterizedTypes2.size();
assert A.class.equals(parameterizedTypes2.get(0).getOwnerType());
assert Map.class.equals(parameterizedTypes2.get(1).getOwnerType());
}
}
GenericArrayType
泛型数组类型,用来作为数组的泛型声明类型。例如
List<T>[] ltArray,T[] tArray两个数组,其中List<T>[], 和T[]就是GenericArrayType类型。
此接口的源码如下:
public interface GenericArrayType extends Type {
//获取泛型类型数组的声明类型,即获取数组方括号 [] 前面的部分
Type getGenericComponentType();
}
GenericArrayType 接口只有一个方法getGenericComponentType(),其可以用来获取数组方括号 [] 前面的部分,例如T[],在其上调用getGenericComponentType 就可以获得T. 值得注意的是多维数组得到的是最后一个[] 前面的部分,例如T[][], 得到的是T[].
测试代码:
public class GenericArrayTypeDemo {
public <T> T[] demo() {
return null;
}
public static void main(String[] args) {
Method[] declaredMethods = GenericArrayTypeDemo.class.getDeclaredMethods();
Method demo = Arrays.stream(declaredMethods).filter(x -> x.getName().equals("demo")).findFirst().orElse(null);
Type returnType = demo.getGenericReturnType();
assert GenericArrayType.class.equals(returnType.getClass());
GenericArrayType aClass = (GenericArrayType) returnType;
Type type = aClass.getGenericComponentType();
assert "T".equals(type.getTypeName());
}
}
WildcardType
通配符类型,即带有
?的泛型参数, 例如List<?>中的?,List<? extends Number>里的? extends Number和List<? super Integer>的? super Integer。
此接口源码如下:
public interface WildcardType extends Type {
// 获取上界
Type[] getUpperBounds();
//获取下界
Type[] getLowerBounds();
}
测试代码:
public class WildcardTypeDemo {
public Class<? extends Object> demo() {
return null;
}
public static void main(String[] args) {
Method[] declaredMethods = WildcardTypeDemo.class.getDeclaredMethods();
Method demo = Arrays.stream(declaredMethods).filter(x -> x.getName().equals("demo")).findFirst().orElse(null);
Type returnType = demo.getGenericReturnType();
ParameterizedType parameterizedType = (ParameterizedType) returnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Type returnArgType0 = actualTypeArguments[0];
WildcardType returnArgWildcardType0 = (WildcardType) returnArgType0;
// upperBounds --> Object
Type[] upperBounds = returnArgWildcardType0.getUpperBounds();
assert Object.class.equals(upperBounds[0]);
}
}
Class
其是
Type的一个实现类,是反射的基础,每一个类在虚拟机中都对应一个Calss 对象,我们可以用在运行时从这个Class对象中获取到类型所有信息。