Java进阶笔记,参照(实则CV)大佬的blog,给大佬👍。 loveshisong.cn/%E7%BC%96%E…
Type类型
Type类型是所有类型的通用父接口,主要包括原始类型,参数化类型,数组类型,类型变量和基本类型。
| 原始类型(raw types) | Class |
| 参数化类型(parameterized types) | ParameterizedType |
| 数组类型(array types) | GenericArrayType |
| 类型变量(type variables) | TypeVariable |
| 基本类型(primitive types) | Class |
ParameterizedType
具体的范型类型,如Map<String, String>
有如下方法:
Type getRawType():返回承载该泛型信息的对象,如上面那个Map承载范型信息的对象是Map。Type[] getActualTypeArguments():返回实际泛型类型列表,如上面那个Map实际范型列表中有两个元素,都是String。Type getOwnerType(): 返回是谁的member。(上面那两个最常用)
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
public class TestType {
Map<String, String> map;
public static void main(String[] args) throws Exception {
Field f = TestType.class.getDeclaredField("map");
System.out.println(f.getGenericType()); // java.util.Map<java.lang.String, java.lang.String>
System.out.println(f.getGenericType() instanceof ParameterizedType); // true
ParameterizedType pType = (ParameterizedType) f.getGenericType();
System.out.println(pType.getRawType()); // interface java.util.Map
for (Type type : pType.getActualTypeArguments()) {
System.out.println(type); // 打印两遍: class java.lang.String
}
System.out.println(pType.getOwnerType()); // null
}
}
TypeVariable
范型信息在编译时会被转换为一个特定的类型,而TypeVariable就是反映jvm在编译该范型前的信息。
Type[] getBounds():获取类型变量的上边界, 若未明确声明上边界则默认为Object。D getGenericDeclaration():获取声明该类型变量实体。String getName():获取在源码中定义时的名字。
注意:
- 类型变量在定义的时候只能使用
extends进行(多)边界限定, 不能用super。
为什么边界是一个数组? 因为类型变量可以通过&进行多个上边界限定,因此上边界有多个。
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import sun.jvm.hotspot.utilities.Assert;
public class TestType<K extends Comparable & Serializable, V> {
K key;
V value;
public static void main(String[] args) throws Exception {
// 获取字段的类型
Field fk = TestType.class.getDeclaredField("key");
Field fv = TestType.class.getDeclaredField("value");
Assert.that(fk.getGenericType() instanceof TypeVariable, "必须为TypeVariable类型");
Assert.that(fv.getGenericType() instanceof TypeVariable, "必须为TypeVariable类型");
TypeVariable keyType = (TypeVariable)fk.getGenericType();
TypeVariable valueType = (TypeVariable)fv.getGenericType();
// getName 方法
System.out.println("getName 方法:");
System.out.println(keyType.getName()); // K
System.out.println(valueType.getName()); // V
// getGenericDeclaration 方法
System.out.println("getGenericDeclaration 方法:");
System.out.println(keyType.getGenericDeclaration()); // class com.test.TestType
System.out.println(valueType.getGenericDeclaration()); // class com.test.TestType
// getBounds 方法
System.out.println("K 的上界:"); // 有两个
for (Type type : keyType.getBounds()) { // interface java.lang.Comparable
System.out.println(type); // interface java.io.Serializable
}
System.out.println("V 的上界:"); // 没明确声明上界的, 默认上界是 Object
for (Type type : valueType.getBounds()) { // class java.lang.Object
System.out.println(type);
}
}
}
GenericArrayType
范型数组,组成数组的元素中有范型则实现了该接口,它的组成元素是ParameterizedType或TypeVariable类型,它只有一个方法:
Type getGenericComponentType();
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
public class TestType<T> {
public static void main(String[] args) throws Exception {
Method method = Test.class.getDeclaredMethods()[0];
// public void com.test.Test.show(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],int[])
System.out.println(method);
Type[] types = method.getGenericParameterTypes(); // 这是 Method 中的方法
for (Type type : types) {
System.out.println(type + " -- " + (type instanceof GenericArrayType));
}
}
}
class Test<T> {
public void show(List<String>[] pTypeArray, T[] vTypeArray, List<String> list, String[] strings,
int[] ints) {}
}
- 第一个参数
List[]的组成元素List是ParameterizedType类型, 打印结果为true - 第二个参数
T[]的组成元素T是TypeVariable类型, 打印结果为true - 第三个参数
List不是数组, 打印结果为false - 第四个参数
String[]的组成元素String是普通对象, 没有范型, 打印结果为false - 第五个参数
int[] pTypeArray的组成元素int是原生类型, 也没有范型, 打印结果为false
WildcardType
该接口表示通配符泛型, 比如? extends Number 和 ? super Integer 它有如下方法:
Type[] getUpperBounds(): 获取范型变量的上界Type[] getLowerBounds(): 获取范型变量的下界
注意:
- 现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
import sun.jvm.hotspot.utilities.Assert;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.WildcardType;
import java.util.List;
public class TestType {
private List<? extends Number> a; // // a没有下界, 取下界会抛出ArrayIndexOutOfBoundsException
private List<? super String> b;
public static void main(String[] args) throws Exception {
Field fieldA = TestType.class.getDeclaredField("a");
Field fieldB = TestType.class.getDeclaredField("b");
// 先拿到范型类型
Assert.that(fieldA.getGenericType() instanceof ParameterizedType, "");
Assert.that(fieldB.getGenericType() instanceof ParameterizedType, "");
ParameterizedType pTypeA = (ParameterizedType)fieldA.getGenericType();
ParameterizedType pTypeB = (ParameterizedType)fieldB.getGenericType();
// 再从范型里拿到通配符类型
Assert.that(pTypeA.getActualTypeArguments()[0] instanceof WildcardType, "");
Assert.that(pTypeB.getActualTypeArguments()[0] instanceof WildcardType, "");
WildcardType wTypeA = (WildcardType)pTypeA.getActualTypeArguments()[0];
WildcardType wTypeB = (WildcardType)pTypeB.getActualTypeArguments()[0];
// 方法测试
System.out.println(wTypeA.getUpperBounds()[0]); // class java.lang.Number
System.out.println(wTypeB.getLowerBounds()[0]); // class java.lang.String
// 看看通配符类型到底是什么, 打印结果为: ? extends java.lang.Number
System.out.println(wTypeA);
}
}
再写几个边界的例子:
List, 上界为class java.lang.Number, 属于Class类型List>, 上界为java.util.List, 属于ParameterizedType类型List>, 上界为java.util.List, 属于ParameterizedType类型List, 上界为T, 属于TypeVariable类型List, 上界为T[], 属于GenericArrayType类型
它们最终统一成Type作为数组的元素类型