反射在java中的应用_java反射机制在项目中的运用
定義:Reflection是java開發語言特性之一,它允許運行中的java程序對自身進行檢測,自審,并能操作程序內部的屬性和方法,Reflection是java被視為動態語言關鍵之一。允許程序從執行期的Reflection APIS取得任何已知名稱的class內部信息,包含packages、type parameters、superclass、implement Interfaces、inner classes、outer class、fields、methods、constructors、modifiers,并可在執行期間執行instance,更變field內容,喚醒method。
反射過程中常用的類:
java反射所需要的類并不多,他們分別是:Class、Constructor、Object、Method、Field。
Class類:每個class都有一個相應的Class對象。也就是說,當我們編寫一個類,編譯完成后,在生成的.class文件中,就會產生一個Class對象,在運行期間如果我們需要產生某個類的對象,JVM就會檢測該類型的Class對象是否已經被加載,如果沒有被加載,則虛擬機會根據類名稱找到并加載相對應的.class文件,一旦某個類型的Class對象加載到內存中,就可以用它來產生相應的對象。
Constructor類:封裝了反射類的構造方法,提供該類單個構造方法和訪問權限信息。
Object類:每個類都使用Object作為超類,所有的對象都實現這個類的方法。
Method類:提供有關類或者接口單獨某個方法的信息,以及動態訪問權限,所反映的方法可能是類方法或者實例方法以及抽象方法。
Field類:提供有關類或者結構單獨屬性的信息,以及動態訪問權限,所反映的屬性可能是類屬性或者實例屬性。
項目中的實際運用:上次在講述Android AIDL IPC通信的時候提到過,基于AIDL實現客戶端被注冊的view通過反射以及服務端傳過來的數據達成一個交互過程。實現圖片文字的顯示過程。
客戶端調用:首先:我們需要實現我們要注冊的MyImageView,繼承自ImageView,主要用來圖片顯示。
package com.zlc.aidl.client;
import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView;
public class MyImageView extends ImageView{
public MyImageView(Context context) {
super(context);
}
@Override
public void setImageBitmap(Bitmap bm) {
// TODO Auto-generated method stub
super.setImageBitmap(bm);
}
}
然后:我們需要反射的工具類ReflectionInvoke.java,用來反射調用注冊view對象里面的方法,通過服務端傳過來的參數和對應方法名來進行反射調用。在工具類中包含一個InvokeKey的內部類,主要用來標示一個對象的某個方法,并保存到工具類集合里面,下次調用的時候不需要再進行尋找method的過程,直接invoke反射調用就行。
package com.zlc.aidl.client;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import android.util.Log;
public class ReflectionInvoke {
public static HashMap> reflections = new HashMap>();
private Method method;
private Class> clazz;
private Class> parameterClasses[];
static class InvokeKey {
String className;
String methodName;
String[] paramsClassName;
public InvokeKey(String className, String methodName, String[] paramsClassName) {
this.className = className;
this.methodName = methodName;
this.paramsClassName = paramsClassName;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
int ret = className.hashCode();
ret = methodName.hashCode() + ret * 10;
for (int i = 0; i < paramsClassName.length; i++) {
ret = paramsClassName[i].hashCode() + ret * 10;
}
return ret;
}
@Override
public boolean equals(Object o) {
if (o instanceof InvokeKey) {
InvokeKey key = (InvokeKey) o;
if (!key.className.equals(className) || !key.methodName.equals(methodName)
|| key.paramsClassName.length != paramsClassName.length) {
return false;
} else {
for (int i = 0; i < paramsClassName.length; i++) {
if (!key.paramsClassName[i].equals(paramsClassName[i]))
return false;
}
return true;
}
}
return false;
}
}
Class> classForNameX(String name) throws Exception {
if ("int".equals(name))
return int.class;
else if ("char".equals(name))
return char.class;
else if ("short".equals(name))
return short.class;
else if ("byte".equals(name))
return byte.class;
else if ("long".equals(name))
return long.class;
else if ("float".equals(name))
return float.class;
else if ("double".equals(name))
return double.class;
else if ("boolean".equals(name))
return boolean.class;
return Class.forName(name);
}
private ReflectionInvoke(InvokeKey key) throws Exception {
clazz = Class.forName(key.className);
parameterClasses = new Class[key.paramsClassName.length];
for (int i = 0; i < parameterClasses.length; i++) {
parameterClasses[i] = classForNameX(key.paramsClassName[i]);
}
method = clazz.getMethod(key.methodName, parameterClasses);
}
public static ReflectionInvoke getInvoker(String className, String methodName,
List argsClassName) {
String[] arrayarges = new String[argsClassName.size()];
argsClassName.toArray(arrayarges);
return getInvoker(className, methodName, arrayarges);
}
public static ReflectionInvoke getInvoker(String className, String methodName, String... args) {
ReflectionInvoke invoke = null;
synchronized (reflections) {
try {
InvokeKey key = new InvokeKey(className, methodName, args);
WeakReference w = reflections.get(key);
if (w == null ? true : (invoke = w.get()) == null) {
invoke = new ReflectionInvoke(key);
reflections.put(key, new WeakReference(invoke));
}
} catch (Exception e) {
e.printStackTrace();
}
}
return invoke;
}
public Object invokeNoException(Object obj, Object... args) {
try {
return method.invoke(obj, args);
} catch (Exception e) {
Log.d("Exception", "invoke error");
}
return null;
}
public Object invoke(Object obj, Object... args) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Log.d("ReflectionInvoke", "invoke invoke invoke");
return method.invoke(obj, args);
}
}
其次:需要準備一個實現parcelable的對象,用來在兩個進程之間傳遞方法名、方法參數等信息。
package com.zlc.aidl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.graphics.Bitmap;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
public class JsonReflectionInvokParcelable implements Parcelable{
public String objectId;
public String methodname;
public List argsClassName;
public List argsVaule;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(objectId);
dest.writeString(methodname);
dest.writeList(argsClassName);
dest.writeList(argsVaule);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public JsonReflectionInvokParcelable createFromParcel(Parcel in) {
JsonReflectionInvokParcelable tp = new JsonReflectionInvokParcelable();
tp.objectId = in.readString();
tp.methodname = in.readString();
tp.argsClassName = new ArrayList();
in.readList(tp.argsClassName, null);
tp.argsVaule = new ArrayList();
in.readList(tp.argsVaule, null);
return tp;
}
public JsonReflectionInvokParcelable[] newArray(int size) {
return new JsonReflectionInvokParcelable[size];
}
};
public void clean() {
for (Object o : argsVaule) {
try {
if (o instanceof ParcelFileDescriptor)
((ParcelFileDescriptor) o).close();
else if (o instanceof Bitmap)
((Bitmap) o).recycle();
} catch (IOException e) {
}
}
}
}
服務端調用
再次:服務端發送數據之前檢測并且封裝參數的類型
……
public void callReflection(String json, String objId, String method,
Object ...args) throws RemoteException {
JsonReflectionInvokParcelable p = new JsonReflectionInvokParcelable();
p.objectId = objId;
p.methodname = method;
p.argsClassName = new ArrayList();
p.argsVaule = new ArrayList();
Log.d(TAG, "callReflection222 json=" + json);
for (int i = 0; i < args.length; i++) {
Object o = args[i];
@SuppressWarnings("rawtypes")
Class clazz = o.getClass();
if (clazz.isPrimitive() || o instanceof Parcelable || o instanceof String
|| o instanceof Integer || o instanceof Short || o instanceof Float
|| o instanceof Double || o instanceof Character) {
p.argsClassName.add(clazz.getCanonicalName());
p.argsVaule.add(o);
} else {
throw new RuntimeException("args only support primitives and String");
}
}
callback.onReflectionCallback(p, json);
Log.d(TAG, "callReflection222 end json=" + json);
}
……
最后:從服務端調用客戶端注冊view的某個指定方法
private final IMyAidlService.Stub mBinder = new IMyAidlService.Stub() {
@Override
public void registerClient(AIDLCallback cb) throws RemoteException {
Log.d(TAG, "registerClient");
callback = cb;
Bitmap bmp = BitmapFactory.decodeFile("/data/data/com.zlc.aidl.server/files/1.jpg");
callReflection("just for test","myImageView","setImageBitmap",bmp);
cb.asBinder().linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
// TODO Auto-generated method stub
try {
Log.i(TAG, "[ServiceAIDLImpl]binderDied.");
} catch (Throwable e) {
}
}
}, 0);
}
};
具體反射的其他一些用途和使用方式,大家可以去問問度娘和谷哥,這有個例子講述了大部分使用方法。
最后附上反射使用實例的源碼,圖片自己下載一張存放到/data/data/com.zlc.aidl.server/files/目錄下,如果沒有files目錄,可通過代碼創建或者通過linux命令創建。
總結
以上是生活随笔為你收集整理的反射在java中的应用_java反射机制在项目中的运用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java集合set的使用_浅析Java中
- 下一篇: 福州联通与市政府携手 共筑新型智慧城市