Java Class 类使用
我们可以通过已知的包名来获取到 Class 对象,从而可以通过反射动态的来操作对象。
获取Class有三种方式
//通过对象.class直接获取
Class integerClass = Integer.class;
//根据包名,通过Class.forName方法获取class
Class integerClass = Class.forName("java.lang.Integer");
//根据包名,通过classloader.loadClass方法获取class
Class integerClass = this.getClass().getClassLoader().loadClass("java.lang.Integer");
接下来根据实际的例子说明一下
public interface InterfaceA {
void interfaceAMethodA(int a);
}
public interface InterfaceB {
Double interfaceBMethodB(int a, String b);
}
public class ClassA implements InterfaceA {
private int classAFieldA;
@Override
public void interfaceAMethodA(int a) {
}
//省略了 getter setter 方法
}
public class ClassB extends ClassA implements InterfaceB{
private String classBFieldB;
@Override
public Double interfaceBMethodB(int a, String b) {
return null;
}
//省略了 getter setter 方法
}
运行一个测试方法
public static void main(String[] args) {
Class clazz = Class.forName("org.dmgnn.reflect.ClassB");
System.out.println("clazz.getGenericSuperclass() = " + JSON.toJSONString(clazz.getGenericSuperclass()));
System.out.println("clazz.getSuperclass() = " + JSON.toJSONString(clazz.getSuperclass()));
Arrays.stream(clazz.getMethods()).forEach(m -> {
System.out.println("clazz.getMethods() -> " + m.getName() + " getParameterTypes -> " + JSON.toJSONString(m.getParameterTypes()) + " getReturnType -> " + m.getReturnType());
});
Arrays.stream(clazz.getDeclaredMethods()).forEach(m -> {
System.out.println("clazz.getDeclaredMethods() -> " + m.getName() + " getParameterTypes -> " + JSON.toJSONString(m.getParameterTypes()) + " getReturnType -> " + m.getReturnType());
});
System.out.println("clazz.getInterfaces() = " + JSON.toJSONString(clazz.getInterfaces()));
System.out.println("clazz.getGenericInterfaces() = " + JSON.toJSONString(clazz.getGenericInterfaces()));
}
//输出
clazz.getGenericSuperclass() = "org.dmgnn.reflect.ClassA"
clazz.getSuperclass() = "org.dmgnn.reflect.ClassA"
clazz.getMethods() -> equals getParameterTypes -> ["java.lang.Object"] getReturnType -> boolean
clazz.getMethods() -> toString getParameterTypes -> [] getReturnType -> class java.lang.String
clazz.getMethods() -> hashCode getParameterTypes -> [] getReturnType -> int
clazz.getMethods() -> builder getParameterTypes -> [] getReturnType -> class org.dmgnn.reflect.ClassB$ClassBBuilder
clazz.getMethods() -> interfaceBMethodB getParameterTypes -> ["int","java.lang.String"] getReturnType -> class java.lang.Double
clazz.getMethods() -> getClassBFieldB getParameterTypes -> [] getReturnType -> class java.lang.String
clazz.getMethods() -> setClassBFieldB getParameterTypes -> ["java.lang.String"] getReturnType -> void
clazz.getMethods() -> interfaceAMethodA getParameterTypes -> ["int"] getReturnType -> void
clazz.getMethods() -> getClassAFieldA getParameterTypes -> [] getReturnType -> int
clazz.getMethods() -> setClassAFieldA getParameterTypes -> ["int"] getReturnType -> void
clazz.getMethods() -> wait getParameterTypes -> ["long","int"] getReturnType -> void
clazz.getMethods() -> wait getParameterTypes -> ["long"] getReturnType -> void
clazz.getMethods() -> wait getParameterTypes -> [] getReturnType -> void
clazz.getMethods() -> getClass getParameterTypes -> [] getReturnType -> class java.lang.Class
clazz.getMethods() -> notify getParameterTypes -> [] getReturnType -> void
clazz.getMethods() -> notifyAll getParameterTypes -> [] getReturnType -> void
clazz.getDeclaredMethods() -> equals getParameterTypes -> ["java.lang.Object"] getReturnType -> boolean
clazz.getDeclaredMethods() -> toString getParameterTypes -> [] getReturnType -> class java.lang.String
clazz.getDeclaredMethods() -> hashCode getParameterTypes -> [] getReturnType -> int
clazz.getDeclaredMethods() -> canEqual getParameterTypes -> ["java.lang.Object"] getReturnType -> boolean
clazz.getDeclaredMethods() -> builder getParameterTypes -> [] getReturnType -> class org.dmgnn.reflect.ClassB$ClassBBuilder
clazz.getDeclaredMethods() -> getClassBFieldB getParameterTypes -> [] getReturnType -> class java.lang.String
clazz.getDeclaredMethods() -> interfaceBMethodB getParameterTypes -> ["int","java.lang.String"] getReturnType -> class java.lang.Double
clazz.getDeclaredMethods() -> setClassBFieldB getParameterTypes -> ["java.lang.String"] getReturnType -> void
clazz.getInterfaces() = ["org.dmgnn.reflect.InterfaceB"]
clazz.getGenericInterfaces() = ["org.dmgnn.reflect.InterfaceB"]
getGenericSuperclass() 和 getSuperclass() 返回父类class
getMethods() 返回当前class以及父类class的所有方法 getDeclaredMethods 返回当前class的方法 getInterfaces() 和 getGenericInterfaces() 返回当前class实现的接口
Type 接口
getGenericSuperclass() 和 getSuperclass() 虽然都是返回的父类class,但是2个方法的返回类型不一样。
public Type getGenericSuperclass() {
ClassRepository info = getGenericInfo();
if (info == null) {
return getSuperclass();
}
// Historical irregularity:
// Generic signature marks interfaces with superclass = Object
// but this API returns null for interfaces
if (isInterface()) {
return null;
}
return info.getSuperclass();
}
public native Class<? super T> getSuperclass();
getSupperClass() 返回的是Class<? super T>
getGenericSuperClass() 返回的是 Type
/**
* Type is the common superinterface for all types in the Java
* programming language. These include raw types, parameterized types,
* array types, type variables and primitive types.
*
* @since 1.5
*/
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
从注释来看,Type 接口是 Java 编程语言中所有类型的通用超级接口。这些包括原始类型,参数化类型,数组类型,类型变量和基本数据类型。 已知的子接口有 GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType
ParameterizedType 使用
ParameterizedType 定义为
public interface ParameterizedType extends Type {
//返回的对象的实际类型参数 Type代表这种类型的数组。
Type[] getActualTypeArguments();
//返回表示的类或接口声明此类型的 Type对象。
Type getRawType();
//返回一个表示该类型的成员 Type对象类型。
Type getOwnerType();
}
看注释有点看不懂,再看一个例子
public class ClassC<T1, T2> {
public void printType() {
System.out.println("clazz.getGenericSuperclass() = " + JSON.toJSONString(getClass().getGenericSuperclass()));
System.out.println("clazz.getActualTypeArguments() = " + JSON.toJSONString(((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()));
}
}
public class ClassD extends ClassC<Integer, String> {
}
public static void main(String[] args) {
ClassD classD = new ClassD();
classD.printType();
}
//输出
clazz.getGenericSuperclass() = {"actualTypeArguments":["java.lang.Integer","java.lang.String"],"rawType":"org.dmgnn.reflect.ClassC","typeName":"org.dmgnn.reflect.ClassC<java.lang.Integer, java.lang.String>"}
clazz.getActualTypeArguments() = ["java.lang.Integer","java.lang.String"]
clazz.getGenericSuperclass() 获取到的是ClassD的父类,也就是ClassC<T1, T2>,这个类接收2个泛型参数。
通过打印出来的日志看到已经获取到了ClassC实际运行时的参数(actualTypeArguments)类型为<Integer, String>,也就是ClassD在继承的时候传到ClassC的参数,原型(rawType)为 org.dmgnn.reflect.ClassC,完整的类名(typeName)为 org.dmgnn.reflect.ClassC<java.lang.Integer, java.lang.String>
那么想要获得ClassC在运行的时的泛型类型,只要调用getActualTypeArguments()方法即可。