1. 程式人生 > >關於Java反射筆記

關於Java反射筆記

原文:https://www.jianshu.com/p/5b3acad0f025

什麼是反射:

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

優缺點:

上面反射機制的定義還是很言簡意賅的。因為反射可以在執行時載入、探知、使用完全未知的類,你只要給我一個路徑就可以了,我通過這個路徑拿到我需要的東西,我的操作與你無關了,靈活性更高了,類之間的耦合性也就降低了。

同時我們可以獲取到類的私有資訊,破壞了類的封裝,使類變得不安全。使用反射還會降低程式效能。所以說使用反射優點突出,缺點同樣突出。

建立一個消費者類:

/**
 * Java反射例子
 *  消費者類
 * @author jinlei
 *
 */
public class Consumer {

    private long id;//私有的
    public String name;//共有的
    /*沒引數構造體*/
    public Consumer() {
    }
    /*有引數構造體*/
    public Consumer(long id, String name) {
        this.id = id;
        this.name = name;
    }
    /*getter setter*/
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    /*私有的無參buy方法*/
    @SuppressWarnings("unused")
    private static void buy() {
        System.out.println("私有的無參buy方法");
    }
    /*共有的有參有返回值consume方法*/
    public String consume(String giftName) {
        System.out.println("買了一件禮物: " + giftName);
        return giftName;
    }
    @Override
    public String toString() {
        return "Consumer [id=" + id + ", name=" + name + "]";
    }

}
/**
 * 反射測試類
 * @author jinlei
 *
 */
public class TestReflect {

    public static void main(String[] args) throws Exception{
        /* 獲取物件型別 */
        Class<?> clazz  = Class.forName("com.jeecms.reflect.Consumer");
        Object object = clazz.newInstance();
           /* 獲取到所有屬性 */
           Field[] field = clazz.getDeclaredFields();
           for (Field f:field) {
               //String fieldName = f.getName();// 取到屬性名字
               //System.out.println(fieldName);
               System.out.println(f);
           }
           /* 獲取到所有的方法,包括私有的,但不包括父類的 */
           Method[] methods = clazz.getDeclaredMethods();
           for (Method m:methods){
               //String methodName = m.getName();
               //System.out.println(methodName);
               System.out.println(m);
           }
           /* 所有的構造體 */
           Constructor[] constructors = clazz.getDeclaredConstructors();
           for (Constructor c:constructors){
               System.out.println(c);
           }
           // 呼叫方法
           Method method = clazz.getMethod("consume", String.class);//獲取方法
           method.invoke(object, "隔壁老王");
           //得到屬性
           Field aField = clazz.getField("name");
           //Field aField = clazz.getDeclaredField("name"); //因為id變數是private的,所以不能用getField方法
           //值為 true 則指示反射的物件在使用時應該取消 Java 語言訪問檢查。值為 false 則指示反射的物件應該實施 Java 語言訪問檢查。
           aField.setAccessible(true);
           aField.set(object,"二大爺");
           Object obj = aField.get(object);
           System.out.println(obj);
           // 得到構造器
           Constructor constructor = clazz.getDeclaredConstructor(long.class, String.class);
           Consumer object2 = (Consumer)constructor.newInstance(2016040221, "王小二");
           System.out.println(object2.toString());
           
    }
}

主要的三個方法:

/* 獲取到所有屬性 */  Field[] field = clazz.getDeclaredFields();

/* 獲取到所有的方法,包括私有的,但不包括父類的 */ Method[] methods = clazz.getDeclaredMethods();

獲取到方法之後呼叫Method 的invoke 方法,就能呼叫了

* 所有的構造體 */  Constructor[] constructors = clazz.getDeclaredConstructors();