Java的類的反射機制和運用淺析

java的反射機制可以說是java開發框架的靈魂所在。
在本篇博客中,我會結合別人大牛博客上所說和自己的理解淺談反射機制的理解和IOC和反射機制的關係。

反射機制的概念

主要是指程序可以訪問,檢測和修改它本身狀態或行爲的一種能力,並能根據自身行爲的狀態和結果,調整或修改應用所描述行爲的狀態和相關的語義。在java中,只要給定類的名字, 那麼就可以通過反射機制來獲得類的所有信息。
反射是Java中一種強大的工具,能夠使我們很方便的創建靈活的代碼,這些代碼可以再運行時裝配,無需在組件之間進行源代碼鏈接。但是反射使用不當會成本很高!
類中有什麼信息,利用反射機制就能可以獲得什麼信息,不過前提是得知道類的名字。

反射機制的作用

1.在運行時判斷任意一個對象所屬的類;
2.在運行時獲取類的對象;
3.在運行時訪問java對象的屬性,方法,構造方法等

反射機制的優缺點

首先要搞清楚爲什麼要用反射機制?直接創建對象不就可以了嗎,這就涉及到了動態與靜態的概念。

靜態編譯:在編譯時確定類型,綁定對象,即通過。

動態編譯:運行時確定類型,綁定對象。動態編譯最大限度發揮了java的靈活性,體現了多態的應用,有以降低類之間的藕合性。

反射機制的優點:可以實現動態創建對象和編譯,體現出很大的靈活性(特別是在J2EE的開發中它的靈活性就表現的十分明顯)。通過反射機制我們可以獲得類的各種內容,進行了反編譯。對於JAVA這種先編譯再運行的語言來說,反射機制可以使代碼更加靈活,更加容易實現面向對象。
 
反射機制的缺點:對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什麼並且它 滿足我們的要求。這類操作總是慢於只直接執行相同的操作。

簡單的反射運用Demo

首先創建一個水果類

public class Fruit {
    private String name;//名字
    private int weight;//重量
    public Fruit(){

    }
    @Override
    public String toString(){
        return "Fruit [\n name = " + name + ",\n weight = " + weight + "\n]";
    }
}

然後創建ReflectDemo主類:

import java.lang.reflect.Field;

public class ReflectDemo {
    public static void main(String[] args){
        Class<?> fruitClass = Fruit.class;
        try {
            Object object = fruitClass.newInstance();
            Field[] fields = fruitClass.getDeclaredFields();
            System.out.println("Fruit所有屬性:");
            for(Field field : fields){
                System.out.println(field);
            }
            Field field = fruitClass.getDeclaredField("name");
            field.setAccessible(true);
            field.set(object,"蘋果");
            Field field2 = fruitClass.getDeclaredField("weight");
            field2.setAccessible(true);
            field2.set(object, 18);
            System.out.println("修改後的Fruit值:");
            System.out.println((Fruit)object);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
}

運行結果:
這裏寫圖片描述
解釋一下以上代碼:
class<?>是一個泛型,具體的解釋這裏就不寫了。
.newInstance()是實例化的一個方法,與new不同方法只能實例化無參的構造方法。
Field是一個屬性類。
.setAccessible是獲得修改的權限,默認是false.
通過這種方式就可以來訪問和修改類中private的屬性值了,是不是很神奇。

工廠模式和運用了反射機制的工廠模式

未用反射機制的工廠模式
首先創建Fruit接口

interface Fruit {
    public abstract void eat();
}

然後分別用兩個實體類來實現這個接口

public class Apple implements Fruit{
    public void eat() {
        System.out.println("Apple");
    }
}

public class Orange implements Fruit{
    @Override
    public void eat() {
        System.out.println("Orange");   
    }

}

最後創造出工廠類:

public class Factory {
    public static Fruit getInstance(String fruitName) {
        Fruit f = null;
        if("Apple".equals(fruitName)) {
            f = new Apple();
        }
        if("Orange".equals(fruitName)) {
            f = new Orange();
        }
        return f;
    }

}

主類運行:

public class Main {

    public static void main(String[] args) {
        Fruit f = Factory.getInstance("Orange");
        f.eat();
    }

}

這樣創建的工廠類,一旦有新的水果產生就要去改工廠類裏面的方法,非常的麻煩,但是運用到了反射機制後,當新增水果的時候就能不需要去更改工廠類的方法。
改動後的工廠類:

public class Factory {
    public static Fruit getInstance(String fruitName) {
        Fruit fruit = null;
        try {
            fruit = (Fruit)Class.forName(fruitName).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return fruit;
    }
}

代碼解釋:

在這裏通過反射機制傳遞類名來進行實例化。這樣就降低了耦合,方便了代碼的擴展。
不過在Main類中要加一個

if(f != null) {
            f.eat();
        }

因爲f有可能爲空。
以上就是我的類的反射機制的和運用的簡單理解,如果有更深或者有誤的,還請多多指出,謝謝,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章