- 相關推薦
Java反射機制應用實踐
引導語:通過反射機制我們可以在運行期間獲取對象的類型信息,利用這一特性我們可以實現工廠模式和代理模式等設計模式,以下是小編整理的Java反射機制應用實踐,歡迎參考閱讀!
反射基礎
p.s: 本文需要讀者對反射機制的API有一定程度的了解,如果之前沒有接觸過的話,建議先看一下官方文檔的Quick Start。
在應用反射機制之前,首先我們先來看一下如何獲取一個對象對應的反射類Class,在Java中我們有三種方法可以獲取一個對象的反射類。
通過getClass方法
在Java中,每一個Object都有一個getClass方法,通過getClass方法我們可以獲取到這個對象對應的反射類:
String s = "ziwenxie";
Class
通過forName方法
我們也可以調用Class類的靜態(tài)方法forName:
Class
使用.class
或者我們也可以直接使用.class:
Class
獲取類型信息
在文章開頭我們就提到反射的一大好處就是可以允許我們在運行期間獲取對象的類型信息,下面我們通過一個例子來具體看一下。
首先我們在typeinfo.interfacea包下面新建一個接口A:
package typeinfo.interfacea;
public interface A { void f(); }
接著我們在typeinfo.packageaccess包下面新建一個接口C,接口C繼承自接口A,并且我們還另外創(chuàng)建了幾個用于測試的方法,注意下面幾個方法的權限都是不同的。
package typeinfo.packageaccess;
import typeinfo.interfacea.A;
class C implements A {
public void f() { System.out.println("public C.f()"); }
public void g() { System.out.println("public C.g()"); }
protected void v () { System.out.println("protected C.v()"); }
void u() { System.out.println("package C.u()"); }
private void w() { System.out.println("private C.w()"); }
}
public class HiddenC {
public static A makeA() { return new C(); }
}
在callHiddenMethod()方法中我們用到了幾個新的API,其中getDeclaredMethod()根據方法名用于獲取Class類指代對象的某個方法,然后我們通過調用invoke()方法傳入實際的對象就可以觸發(fā)對象的相關方法:
package typeinfo;
import typeinfo.interfacea.A;
import typeinfo.packageaccess.HiddenC;
import java.lang.reflect.Method;
public class HiddenImplementation {
public static void main(String[] args) throws Exception {
A a = HiddenC.makeA();
a.f();
System.out.println(a.getClass().getName());
// Oops! Reflection still allows us to call g():
callHiddenMethod(a, "g");
// And even methods that are less accessible!
callHiddenMethod(a, "u");
callHiddenMethod(a, "v");
callHiddenMethod(a, "w");
}
static void callHiddenMethod(Object a, String methodName) throws Exception {
Method g = a.getClass().getDeclaredMethod(methodName);
g.setAccessible(true);
g.invoke(a);
}
}
從輸出結果我們可以看出來,不管是public,default,protect還是pricate方法,通過反射類我們都可以自由調用。當然這里我們只是為了顯示反射的強大威力,在實際開發(fā)中這種技巧還是不提倡。
public C.f()
typeinfo.packageaccess.C
public C.g()
package C.u()
protected C.v()
private C.w()
應用實踐
我們有下面這樣一個業(yè)務場景,我們有一個泛型集合類List<Class>,我們需要統計出這個集合類中每種具體的Pet有多少個。由于Java的泛型擦除,注意類似List的做法肯定是不行的,因為編譯器做了靜態(tài)類型檢查之后,到了運行期間JVM會將集合中的對象都視為Pet,但是并不會知道Pet代表的究竟是Cat還是Dog,所以到了運行期間對象的類型信息其實全部丟失了。p.s: 關于泛型擦除:我在上一篇文章里面有詳細解釋,感興趣的朋友可以看一看。
為了實現我們上面的例子,我們先來定義幾個類:
public class Pet extends Individual {
public Pet(String name) { super(name); }
public Pet() { super(); }
}
public class Cat extends Pet {
public Cat(String name) { super(name); }
public Cat() { super(); }
}
public class Dog extends Pet {
public Dog(String name) { super(name); }
public Dog() { super(); }
}
public class EgyptianMau extends Cat {
public EgyptianMau(String name) { super(name); }
public EgyptianMau() { super(); }
}
public class Mutt extends Dog {
public Mutt(String name) { super(name); }
public Mutt() { super(); }
}
上面的Pet類繼承自Individual,Individual類的的實現稍微復雜一點,我們實現了Comparable接口,重新自定義了類的比較規(guī)則,如果不是很明白的話,也沒有關系,我們已經將它抽象出來了,所以不理解實現原理也沒有關系。
public class Individual implements Comparable
private static long counter = 0;
private final long id = counter++;
private String name; // name is optional
public Individual(String name) { this.name = name; }
public Individual() {}
public String toString() {
return getClass().getSimpleName() + (name == null ? "" : " " + name);
}
public long id() { return id; }
public boolean equals(Object o) {
return o instanceof Individual && id == ((Individual)o).id;
}
public int hashCode() {
int result = 17;
if (name != null) {
result = 37 * result + name.hashCode();
}
result = 37 * result + (int) id;
return result;
}
public int compareTo(Individual arg) {
// Compare by class name first:
String first = getClass().getSimpleName();
String argFirst = arg.getClass().getSimpleName();
int firstCompare = first.compareTo(argFirst);
if (firstCompare != 0) {
return firstCompare;
}
if (name != null && arg.name != null) {
int secendCompare = name.compareTo(arg.name);
if (secendCompare != 0) {
return secendCompare;
}
}
return (arg.id < id ? -1 : (arg.id == id ? 0 : 1));
}
}
下面創(chuàng)建了一個抽象類PetCreator,以后我們通過調用arrayList()方法便可以直接獲取相關Pet類的集合。這里使用到了我們上面沒有提及的newInstance()方法,它會返回Class類所真正指代的類的實例,這是什么意思呢?比如說聲明new Dog().getClass().newInstance()和直接new Dog()是等價的。
public abstract class PetCreator {
private Random rand = new Random(47);
// The List of the different getTypes of Pet to create:
public abstract List<Class> getTypes();> allTypes = Collections.unmodifiableList(> types = allTypes.subList(> getTypes() {, Integer> { baseType; baseType) { type = obj.getClass(); type) { superClass = type.getSuperclass();, Integer> pair : entrySet()) {
result.append(pair.getKey().getSimpleName());
result.append("=");
result.append(pair.getValue());
result.append(", ");
}
result.(result.length() - 2, result.length());
result.append("} ");
return result.toString();
}
}
【Java反射機制應用實踐】相關文章:
Java反射機制07-02
java中反射機制11-11
Java反射機制學習總結10-02
Java實現反射學習函數的應用10-22
java的緩存機制07-29
關于Java 反射的簡介08-27
java ClassLoader機制講解07-31
java的緩存機制簡介09-06
java使用反射技術示例06-18