java-反射回顧筆記

Class和class

回顧java的數據類型,基本數據類型和引用數據類型,int,long,float,double,boolean,Object(?)
除了使用java定義的基本數據類型,自定義的類(或者接口)也是一種類型-- Class,每個類都有一個對應的Class實例

//如
Class class = new Class();
以String類爲例,當JVM加載String類時,它首先讀取String.class文件到內存,然後,爲String類創建一個Class實例並關聯起來:
Class cls = new Class(String);

而這個class實例是jvm在第一次加載某個類的時候自動創建的,注意我們用戶並不能創建Class,代碼層面解釋的話就是Class類的構造方法是private類型的,這個Class實例保存了這個類的字段,方法,繼承結構等等的信息,通過這個Class實例獲取對應類(class)信息的方式,就叫反射

獲取Class實例

//1.
Class c1= String.class;
//2.
String s = new String();
Class c2= s.getClass();
//3.
Class c3= Class.forName("java.lang.String");

獲取字段信息

Field f1 = c2.getField("length");//根據字段名獲取某個public的field(包括父類)(注意是public限制符)
Field f2 = c2.getDeclaredField("length");//根據字段名獲取當前類的某個field(不包括父類)(沒有限制符的限制)
Field[] f3 = c2.getFields();//同上
Field[] f4 = c2.getDeclaredFields();
//獲取字段值
Object value = f.get(s);
System.out.println(value); 
//修改值
f.set(s,"sth");

獲取成員方法信息

Method getMethod(name, Class...)//方法參數的Class實例,方法的意義同上
Method getDeclaredMethod(name, Class...)
Method[] getMethod()
Method[] getDeclaredMethod()

//public方法調用
invoke(Instance , Object...)//實例,方法入參
//靜態方法調用
invoke(null, Object...)//靜態方法與實例對象沒有聯繫,所以傳入的第一個參數永遠爲null(經過試驗,調用靜態方法第一個參數不影響調用)
//非公共方法調用同上公共方法,但是可能會調用失敗,拋出IllegalAccessException
setAccessible(true);
//通過調用這個方法允許其調用,不過也可能會失敗,jvm爲了保護自己的核心類庫會不允許

構造方法

有Class實例後可以使用Class實例創建新的實例對象0

String s= = String.class.newInstance();

這種創建方式的侷限是隻能調用該類的public無參構造方法,如果構造方法帶有參數,或者不是public,就無法直接通過Class.newInstance()來調用
同樣,java反射api也有構造方法的操作類,基本和Method一樣,但是構造方法返回的結果就是一個實例,因爲它是構造方法

Constructor cons = String.class.getConstructor(parameterTypes...);//無參可以傳null

獲取父類的Class

        Class n = s.getSuperclass();

獲取實現的接口

	Class[] is = s.getInterfaces();

JDK動態代理

學習spring的過程中瞭解到的一個用法,我認爲jdk的動態代理有一個最大的侷限就是隻能代理接口
先定義了接口Hello,但是並不去編寫實現類,而是直接通過JDK提供的一個 Proxy.newProxyInstance() 創建了一個Hello接口對象。這種沒有實現類但是在運行期動態創建了一個接口對象的方式,稱爲動態代碼。JDK提供的動態創建接口對象的方式,就叫動態代理。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
    public static void main(String[] args) {
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println(method);
                if (method.getName().equals("morning")) {
                    System.out.println("Good morning, " + args[0]);
                }
                return null;
            }
        };
        Hello hello = (Hello) Proxy.newProxyInstance(
            Hello.class.getClassLoader(), // 傳入ClassLoader
            new Class[] { Hello.class }, // 傳入要實現的接口
            handler); // 傳入處理調用方法的InvocationHandler
        hello.morning("Bob");
    }
}

interface Hello {
    void morning(String name);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章