1. 程式人生 > >Java反射機制(超詳細)

Java反射機制(超詳細)

文章目錄

反射機制是什麼

反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制

反射機制能做什麼

  • 在執行時判斷任意一個物件所屬的類;
  • 在執行時構造任意一個類的物件;
  • 在執行時判斷任意一個類所具有的成員變數和方法;
  • 在執行時呼叫任意一個物件的方法;
  • 生成動態代理

案例

通過一個物件獲得完整的包名和類名

package net.xsoftlab.baike;
public class
TestReflect { public static void main(String[] args) throws Exception { TestReflect testReflect = new TestReflect(); System.out.println(testReflect.getClass().getName()); // 結果 net.xsoftlab.baike.TestReflect } }

例項化Class類物件

package net.xsoftlab.baike;
public class
TestReflect { public static void main(String[] args) throws Exception { Class<?> class1 = null; Class<?> class2 = null; Class<?> class3 = null; // 一般採用這種形式 class1 = Class.forName("net.xsoftlab.baike.TestReflect"); class2 = new TestReflect().getClass(); class3 = TestReflect.class; System.out.println("類名稱 " + class1.getName()); System.out.println("類名稱 " + class2.getName()); System.out.println("類名稱 " + class3.getName()); } }

獲取一個物件的父類與實現的介面

package net.xsoftlab.baike;
import java.io.Serializable;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        // 取得父類
        Class<?> parentClass = clazz.getSuperclass();
        System.out.println("clazz的父類為:" + parentClass.getName());
        // clazz的父類為: java.lang.Object

        // 獲取所有的介面
        Class<?> intes[] = clazz.getInterfaces();
        System.out.println("clazz實現的介面有:");
        for (int i = 0; i < intes.length; i++) {
            System.out.println((i + 1) + ":" + intes[i].getName());
        }
        // clazz實現的介面有:
        // 1:java.io.Serializable
    }
}

通過反射機制例項化一個類的物件

package net.xsoftlab.baike;
import java.lang.reflect.Constructor;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> class1 = null;
        class1 = Class.forName("net.xsoftlab.baike.User");
        // 第一種方法,例項化預設構造方法,呼叫set賦值
        User user = (User) class1.newInstance();
        user.setAge(20);
        user.setName("Rollen");
        System.out.println(user);
        // 結果 User [age=20, name=Rollen]

        // 第二種方法 取得全部的建構函式 使用建構函式賦值
        Constructor<?> cons[] = class1.getConstructors();
        // 檢視每個構造方法需要的引數
        for (int i = 0; i < cons.length; i++) {
            Class<?> clazzs[] = cons[i].getParameterTypes();
            System.out.print("cons[" + i + "] (");
            for (int j = 0; j < clazzs.length; j++) {
                if (j == clazzs.length - 1)
                    System.out.print(clazzs[j].getName());
                else
                    System.out.print(clazzs[j].getName() + ",");
            }
            System.out.println(")");
        }
        // 結果
        // cons[0] (java.lang.String)
        // cons[1] (int,java.lang.String)
        // cons[2] ()

        user = (User) cons[0].newInstance("Rollen");
        System.out.println(user);
        // 結果 User [age=0, name=Rollen]

        user = (User) cons[1].newInstance(20, "Rollen");
        System.out.println(user);
        // 結果 User [age=20, name=Rollen]
    }
}
class User {
    private int age;
    private String name;
    public User() {
        super();
    }
    public User(String name) {
        super();
        this.name = name;
    }
    public User(int age, String name) {
        super();
        this.age = age;
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + "]";
    }
}

獲取某個類的全部屬性

package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        System.out.println("===============本類屬性===============");
        // 取得本類的全部屬性
        Field[] field = clazz.getDeclaredFields();
        for (int i = 0; i < field.length; i++) {
            // 許可權修飾符
            int mo = field[i].getModifiers();
            String priv = Modifier.toString(mo);
            // 屬性型別
            Class<?> type = field[i].getType();
            System.out.println(priv + " " + type.getName() + " " + field[i].getName() + ";");
        }
         
        System.out.println("==========實現的介面或者父類的屬性==========");
        // 取得實現的介面或者父類的屬性
        Field[] filed1 = clazz.getFields();
        for (int j = 0; j < filed1.length; j++) {
            // 許可權修飾符
            int mo = filed1[j].getModifiers();
            String priv = Modifier.toString(mo);
            // 屬性型別
            Class<?> type = filed1[j].getType();
            System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
        }
    }
}

獲得某個類的全部方法

package net.xsoftlab.baike;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class TestReflect implements Serializable {
    private static final long serialVersionUID = -2862585049955236662L;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Method method[] = clazz.getMethods();
        for (int i = 0; i < method.length; ++i) {
            Class<?> returnType = method[i].getReturnType();
            Class<?> para[] = method[i].getParameterTypes();
            int temp = method[i].getModifiers();
            System.out.print(Modifier.toString(temp) + " ");
            System.out.print(returnType.getName() + " ");
            System.out.print(method[i].getName() + " ");
            System.out.print("(");
            for (int j = 0; j < para.length; ++j) {
                System.out.print(para[j].getName() + " " + "arg" + j);
                if (j < para.length - 1) {
                    System.out.print(",");
                }
            }
            Class<?> exce[] = method[i].getExceptionTypes();
            if (exce.length > 0) {
                System.out.print(") throws ");
                for (int k = 0; k < exce.length; ++k) {
                    System.out.print(exce[k].getName() + " ");
                    if (k < exce.length - 1) {
                        System.out.print(",");
                    }
                }
            } else {
                System.out.print(")");
            }
            System.out.println();
        }
    }
}

通過反射機制呼叫某個類的方法

package net.xsoftlab.baike;
import java.lang.reflect.Method;
public class TestReflect {
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        // 呼叫TestReflect類中的reflect1方法
        Method method = clazz.getMethod("reflect1");
        method.invoke(clazz.newInstance());
        // Java 反射機制 - 呼叫某個類的方法1.
  
        // 呼叫TestReflect的reflect2方法
        method = clazz.getMethod("reflect2", int.class, String.class);
        method.invoke(clazz.newInstance(), 20, "張三");
        // Java 反射機制 - 呼叫某個類的方法2.
        // age -> 20. name -> 張三
    }
    public void reflect1() {
        System.out.println("Java 反射機制 - 呼叫某個類的方法1.");
    }
    public void reflect2(int age, String name) {
        System.out.println("Java 反射機制 - 呼叫某個類的方法2.");
        System.out.println("age -> " + age + ". name -> " + name);
    }
}

通過反射機制操作某個類的屬性

package net.xsoftlab.baike;
import java.lang.reflect.Field;
public class TestReflect {
    private String proprety = null;
    public static void main(String[] args) throws Exception {
        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
        Object obj = clazz.newInstance();
        // 可以直接對 private 的屬性賦值
        Field field = clazz.getDeclaredField("proprety");
        field.setAccessible(true);
        field.set(obj, "Java反射機制");
        System.out.println(field.get(obj));
    }
}

反射機制的動態代理

package net.xsoftlab.baike;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//定義專案介面
interface Subject {
    public String say(String name, int age);
}
// 定義真實專案
class RealSubject implements Subject {
    public String say(String name, int age) {
        return name + " " + age;
    }
}
class MyInvocationHandler implements InvocationHandler {
    private Object obj = null;
    public Object bind(Object obj) {
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object temp = method.invoke(this.obj, args);
        return temp;
    }
}
/**
 * 在java中有三種類類載入器。
 * 1)Bootstrap ClassLoader 此載入器採用c++編寫,一般開發中很少見。
 * 2)Extension ClassLoader 用來進行擴充套件類的載入,一般對應的是jrelibext目錄中的類
 * 3)AppClassLoader