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有可能爲空。
以上就是我的類的反射機制的和運用的簡單理解,如果有更深或者有誤的,還請多多指出,謝謝,