曾经,兄弟我对那些使用java reflect(反射)的大神是五体投地的仰慕,觉得那些神仙一般的人物真是历害,能做用传说中的绝世神功,在java的世界,没有任何的限制,可以对一个对象的所有方法和变量进行读写。
今天,因为要解决一个bug,就对reflect研究了一下,做了一个demo:
reflect主要是对java对象实现访问,修改,包括所有的变量,方法,构造方法。这就给使用者,提供了一种方式,冲破了private对变量和方法的限制,可以随心所欲的对变量进行操作,特别是在android开发中,我们可以使用reflect对系统中的private,hide方法进行调用。reflect是在java.lang.reflect中。
这个Demo,主要是对private变量进行读取,并设置,对private方法进行调用,对private构造方法进行构造新的对象,
1.MyTestClass.java
import android.util.Log; public class MyTestClass { public static final String TAG = "MyTestClass"; private int aInt = 0; private boolean bBoolean = false; private String sString = "test"; public MyTestClass(){ Log.i(TAG,"MyTestClass()"); } private MyTestClass(int aInt,boolean bBoolean,String sString){ Log.i(TAG,"MyTestClass(int aInt,boolean bBoolean,String sString)"); this.aInt = aInt; this.bBoolean = bBoolean; this.sString = sString; } private void setInt(int aInt){ Log.i(TAG,"setInt(int aInt)"); this.aInt = aInt; } private void setBoolean(boolean bBoolean){ Log.i(TAG,"setBoolean(boolean bBoolean)"); this.bBoolean = bBoolean; } private void setString(String sString){ Log.i(TAG,"setString(String sString)"); this.sString = sString; } private void getVariable(){ Log.i(TAG,"getVariable()"); Log.i(TAG,"aInt:" + aInt + "---bBoolean:" + bBoolean + "----sString:" + sString); } }
2.TestReflectActivity.java
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; public class TestReflectActivity extends Activity { public static final String TAG = "MyTestClass"; private MyTestClass myTestClass; private Class myClass; private Method method; private Constructor constructor; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_reflect); myTestClass = new MyTestClass(); myClass = myTestClass.getClass(); try { method = myClass.getDeclaredMethod("getVariable", new Class[]{}); method.setAccessible(true); method.invoke(myTestClass, new Class[]{}); Field aInt = myClass.getDeclaredField("aInt"); aInt.setAccessible(true); Log.i(TAG,"aInt.getName:"+aInt.getName()); Log.i(TAG,"aInt.get(myTestClass):"+ aInt.get(myTestClass)); aInt.setInt(myTestClass, 1); Log.i(TAG,"aInt.get(myTestClass):"+ aInt.get(myTestClass)); Field bBoolean = myClass.getDeclaredField("bBoolean"); bBoolean.setAccessible(true); Log.i(TAG,"bBoolean.getName:"+bBoolean.getName()); Log.i(TAG,"bBoolean.get(myTestClass):"+ bBoolean.get(myTestClass)); bBoolean.setBoolean(myTestClass, true); Log.i(TAG,"bBoolean.get(myTestClass):"+ bBoolean.get(myTestClass)); Field sString = myClass.getDeclaredField("sString"); sString.setAccessible(true); Log.i(TAG,"sString.getName:"+sString.getName()); Log.i(TAG,"sString.get(myTestClass):"+ sString.get(myTestClass)); sString.set(myTestClass, "set_String"); Log.i(TAG,"sString.get(myTestClass):"+ sString.get(myTestClass)); method = myClass.getDeclaredMethod("getVariable", new Class[]{}); method.setAccessible(true); method.invoke(myTestClass, new Class[]{}); method = myClass.getDeclaredMethod("setInt", new Class[]{int.class}); method.setAccessible(true); method.invoke(myTestClass, 2); method = myClass.getDeclaredMethod("setBoolean", new Class[]{boolean.class}); method.setAccessible(true); method.invoke(myTestClass, false); method = myClass.getDeclaredMethod("setString", new Class[]{String.class}); method.setAccessible(true); method.invoke(myTestClass, "set_method"); method = myClass.getDeclaredMethod("getVariable", new Class[]{}); method.setAccessible(true); method.invoke(myTestClass, new Class[]{}); constructor = myClass.getDeclaredConstructor(new Class[]{int.class,boolean.class,String.class}); constructor.setAccessible(true); myTestClass = (MyTestClass) constructor.newInstance(100,false,"test_constructor"); method = myClass.getDeclaredMethod("getVariable", new Class[]{}); method.setAccessible(true); method.invoke(myTestClass, new Class[]{}); } catch (Exception e) { // TODO: handle exception Log.i(TAG,e.toString()); } } }
01-01 10:16:56.259: I/MyTestClass(9174): MyTestClass()
01-01 10:16:56.260: I/MyTestClass(9174): getVariable()
01-01 10:16:56.260: I/MyTestClass(9174): aInt:0---bBoolean:false----sString:test
01-01 10:16:56.260: I/MyTestClass(9174): aInt.getName:aInt
01-01 10:16:56.260: I/MyTestClass(9174): aInt.get(myTestClass):0
01-01 10:16:56.260: I/MyTestClass(9174): aInt.get(myTestClass):1
01-01 10:16:56.261: I/MyTestClass(9174): bBoolean.getName:bBoolean
01-01 10:16:56.261: I/MyTestClass(9174): bBoolean.get(myTestClass):false
01-01 10:16:56.264: I/MyTestClass(9174): bBoolean.get(myTestClass):true
01-01 10:16:56.264: I/MyTestClass(9174): sString.getName:sString
01-01 10:16:56.264: I/MyTestClass(9174): sString.get(myTestClass):test
01-01 10:16:56.265: I/MyTestClass(9174): sString.get(myTestClass):set_String
01-01 10:16:56.265: I/MyTestClass(9174): getVariable()
01-01 10:16:56.268: I/MyTestClass(9174): aInt:1---bBoolean:true----sString:set_String
01-01 10:16:56.268: I/MyTestClass(9174): setInt(int aInt)
01-01 10:16:56.273: I/MyTestClass(9174): setBoolean(boolean bBoolean)
01-01 10:16:56.273: I/MyTestClass(9174): setString(String sString)
01-01 10:16:56.276: I/MyTestClass(9174): getVariable()
01-01 10:16:56.276: I/MyTestClass(9174): aInt:2---bBoolean:false----sString:set_method
01-01 10:16:56.276: I/MyTestClass(9174): MyTestClass(int aInt,boolean bBoolean,String sString)
01-01 10:16:56.276: I/MyTestClass(9174): getVariable()
01-01 10:16:56.276: I/MyTestClass(9174): aInt:100---bBoolean:false----sString:test_constructor