目錄
一、Class類的使用與動態加載類
package com.study.reflect;
/**
* 類功能描述:Class類的使用
*
* @author:***
* @createTime:2018/11/12 16:33
*/
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//任何一個類都是Class的實例對象,這個實例對象有三種表達方式 c1==c2==c3
//c1 c2 c3 是DemoA的類類型(class type)
DemoA demoA = new DemoA();
Class c1 = demoA.getClass();
Class c2 = DemoA.class;
//Class.forName動態加載類(運行時加載類) new是靜態加載類(編譯時加載類)
Class c3 = Class.forName("com.study.reflect.DemoA");
System.out.println(c1 == c2 && c2 == c3 && c3 == c1); //輸出true
//通過類類型創建該類的對象實例 newInstance()
((DemoA) c1.newInstance()).print(); //輸出print
}
}
class DemoA {
void print() {
System.out.println("print");
}
}
二、JAVA獲取方法、成員變量、構造函數信息
class DemoA {
public void print() {
System.out.println("print");
}
public static void main(String[] args) throws NoSuchMethodException {
DemoB.printMethodInfo("hello");
DemoB.printMethodInfo(1);
}
}
class DemoB {
public static void printMethodInfo(Object obj) throws NoSuchMethodException {
Class objClass = obj.getClass();
//java.lang.String
System.out.println("類名稱爲:" + objClass.getName());
//String
System.out.println(objClass.getSimpleName());
//getMethod獲取所有public的函數,包括父類繼承而來的
System.out.println(objClass.getMethod("toString").getName());
//getDeclaredMethod獲取的是所有該類自己聲明的方法,無視訪問權限
System.out.println(objClass.getDeclaredMethod("toString").getName());
//方法也是對象
//遍歷方法列表
Method[] methods = objClass.getMethods();
for (Method method : methods) {
System.out.print(method.getName() + "(");
//遍歷參數名,並打印
Class[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
System.out.print(parameterTypes[i].getSimpleName());
if (i < parameterTypes.length - 1) {
System.out.print(",");
}
}
System.out.println(")");
}
//成員變量也是對象
//遍歷成員變量列表
Field[] fields = objClass.getFields();
for (Field field : fields) {
//遍歷成員遍歷並打印
System.out.println(field.getType() + " " + field.getName());
}
//構造函數也是對象
//構造函數列表
Constructor[] constructors = objClass.getConstructors();
for (Constructor constructor : constructors) {
//構造函數方法名
System.out.print(constructor.getName());
//遍歷構造函數參數列表
Class[] typeParameters = constructor.getParameterTypes();
System.out.print("(");
for (int i = 0; i < typeParameters.length; i++) {
//打印參數名
System.out.print(typeParameters[i].getSimpleName());
if (i < typeParameters.length - 1) {
System.out.print(",");
}
}
System.out.println(")");
}
}
}
三、方法反射的基本操作
class DemoC {
public void test(int a, int b) {
System.out.println(a + b);
}
}
class DemoA {
/**
* 反射就是將類別的各個組成部分進行剖析,可以得到每個組成部分,就可以對每一部分進行操作
* 在比較複雜的程序或框架中來使用反射技術,可以簡化代碼提高程序的複用性。
* 我對invoke理解:運用反射,可以避過編譯時檢查,
* 像方法test可以通過入參的形式調用,如果沒有test這個方法,使用傳統的調用方式,編譯都無法通過
* 可以編寫統一的反射方法,當增加或刪除某個方法時,這個反射方法就不用做一些變動了,可以簡化代碼提高複用。
* 類 方法 字段等都是在運行時纔會執行,通過invoke方法,可以繞過編譯。
* 例如 ArrayList<String> arr = new ArrayList<>(); 可以通過反射繞過編譯,從而添加進其他類型的值
* Method method = arr.getClass().getMethod("add", Object.class);
* method.invoke(arr, 20);
* System.out.println(arr); 輸出20,已經添加進去了
*/
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
DemoC democ = new DemoC();
Method test = democ.getClass().getMethod("test", new Class[]{int.class, int.class});
Object object = test.invoke(democ, new Object[]{10, 20});
}
}