咱們能夠經過已知的包名來獲取到 Class 對象,從而能夠經過反射動態的來操做對象。
獲取Class有三種方式java
//經過對象.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實現的接口編程語言
getGenericSuperclass() 和 getSuperclass() 雖然都是返回的父類class,可是2個方法的返回類型不同。ide
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>, WildcardTypeui
ParameterizedType 定義爲this
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()方法便可。code