看了张明云的博客,稍微总结一下,例子还是用他的
方法、属性的归属问题,属于Class的就传Class的实例,属于类实例的就传入类实例。static修饰符修饰的属性、方法是属于Class的,非static修饰符修饰的方法、属性是属于类实例的。
new : 反射内部类
public class MMP {
private class Boo {
private void showMeWhatUGot(String s) {
System.out.println("showMeWhatUGot:" + s);
}
private void due() {
}
}
}
let's go !
private void showMeWhatUGot() throws Exception {
Class<?> outClz = Class.forName("another_pkg.MMP");
Object out = outClz.newInstance();
Class<?> innerClz = Class.forName("another_pkg.MMP$Boo");
Constructor inner = innerClz.getDeclaredConstructor(outClz);
inner.setAccessible(true);
Object boo = inner.newInstance(out);
Method method = innerClz.getDeclaredMethod("showMeWhatUGot", String.class);
method.setAccessible(true);
method.invoke(boo, "u know nothing");
}
参考 : https://stackoverflow.com/a/17485341/4923470
反射方法封装库
父类:Person
public class Person {
private String mName;
String mSex;
public int mAge;
private static String L;
private static final int G_F = 100;
public Person(String aName, String aSex, int aAge) {
mName = aName;
mSex = aSex;
mAge = aAge;
}
public int getmAge() {
return mAge;
}
public void setmAge(int mAge) {
this.mAge = mAge;
}
public String getmName() {
return mName;
}
public void setmName(String mName) {
this.mName = mName;
}
public String getmSex() {
return mSex;
}
public void setmSex(String mSex) {
this.mSex = mSex;
}
private String getDescription() {
return "黄种人";
}
private static void setStatic(String s) {
Log.e(TAG, "setStatic :" + s);
}
}
接口:
public interface ICompany {
String getCompany();
}
子类:ProgramMonkey
public class ProgramMonkey extends Person implements ICompany {
String mLanguage = "C#";
String mCompany = "BBK";
public ProgramMonkey(String aName, String aSex, int aAge) {
super(aName, aSex, aAge);
}
public ProgramMonkey(String language, String company, String aName, String aSex, int aAge) {
super(aName, aSex, aAge);
mLanguage = language;
mCompany = company;
}
public String getmLanguage() {
return mLanguage;
}
public void setmLanguage(String mLanguage) {
this.mLanguage = mLanguage;
}
private int getSalaryPerMonth() {
return 12306;
}
@Override
public String getCompany() {
return mCompany;
}
}
获取Class实例
private Class<?> getClassObject_1(){
return ProgramMonkey.class;
}
private Class<?> getClassObject_2(){
ProgramMonkey programMonkey = new ProgramMonkey("小明", "男", 12);
return programMonkey.getClass();
}
private Class<?> getClassObject_3(){
try{
return Class.forName("com.eebbk.reflectdemo.ProgramMonkey");
}catch(ClassNotFoundException e){
e.printStackTrace();
}
return null;
}
效果相同
获取构造函数
private void getConstructor() {
Class<?> cls = Person.class;
try {
//构造方法的参数要填全,不管是否private都管用
Constructor<?> constructor = cls.getDeclaredConstructor(String.class, String.class, int.class);
constructor.setAccessible(true);
LogE(1);
LogE("constructor's name:" + constructor.getName());
LogE(2);
Person newPerson = (Person) constructor.newInstance("pepelu", "kick ass", 233);
LogE("new person name:" + newPerson.getmName());
} catch (Exception e) {
e.printStackTrace();
}
}
getDeclaredConstructor()获取在Person.java文件中声明的构造方法,不管是不是private,都能取到,如果构造方法是private的,注意要用constructor.setAccessible(true)获取它的调用权限,getDeclaredConstructor()的参数是构造方法的参数的Class类型。
使用constructor.newInstance()获取Person类的实例,方法参数为构造函数的参数。
获取类中的方法
/**
* 反射执行方法
*/
private void getAllMethods() {
ProgramMonkey programMonkey = new ProgramMonkey("ming", "male", 12);
Log.e(TAG, "-----------1---------------");
//获取ProgramMonkey类和其父类Person类、Object类中的所有public方法
Method[] methods = programMonkey.getClass().getMethods();
for (Method method : methods) {
Log.e(TAG, "get all methods:" + method.getName());
}
try {
//获取ProgramMonkey或者是其父类中的public setmLanguage()方法
Method setMLanguageMethod = programMonkey.getClass().getMethod("setmLanguage", String.class);
setMLanguageMethod.setAccessible(true);
Log.e(TAG, "-----------2---------------");
// 获取setmLanguage()方法返回类型
Class<?> returnType = setMLanguageMethod.getReturnType();
Log.e(TAG, "setmLanguage 方法的返回类型 :" + returnType.getName());//return void
Log.e(TAG, "-----------3---------------");
// 获取setmLanguage()方法的参数类型列表
Class<?>[] paramClasses = setMLanguageMethod.getParameterTypes();
for (Class<?> cla : paramClasses) {
Log.e(TAG, "setmLanguage 方法的参数类型:" + cla.getName());
}
Log.e(TAG, "-----------4---------------");
// 是否是 private 函数,属性是否是 private 也可以使用这种方式判断
Log.e(TAG, setMLanguageMethod.getName() + " is private :"
+ Modifier.isPrivate(setMLanguageMethod.getModifiers()));
Log.e(TAG, "-----------5---------------");
// 执行setmLanguage()方法
Object result = setMLanguageMethod.invoke(programMonkey, "Java");
Log.e(TAG, "setmLanguage 方法的返回结果:" + result);
Log.e(TAG, "-----------6---------------");
//获取反射执行后的效果,programMonkey同一实例
Log.e(TAG, "language :" + programMonkey.getmLanguage());
Log.e(TAG, "-----------7---------------");
//获取并执行Person类中的static方法
Class<?> clsPerson = Person.class;
Method methodPerson = clsPerson.getDeclaredMethod("setStatic", String.class);
methodPerson.setAccessible(true);
//都可以,setStatic()方法是静态方法,从属于Person的Class而非Person的实例
methodPerson.invoke(clsPerson, "from main activity");
//methodPerson.invoke(null, "from main activity");
} catch (Exception e) {
e.printStackTrace();
}
}
获取自己类和父类中的非静态属性
private void getAllFields() {
ProgramMonkey programMonkey = new ProgramMonkey("ming", "male", 123);
LogE(0);
//获取在ProgramMonkey.java文件中声明的所有属性
Field[] declarFields = programMonkey.getClass().getDeclaredFields();
for (Field f : declarFields) {
LogE("declar fields:" + f.getName());
}
LogE(1);
// 获取当前类和父类的所有公有属性
Field[] publicFields = programMonkey.getClass().getFields();
for (Field f : publicFields) {
LogE("getFields field name : " + f.getName());
}
LogE(2);
try {
// 获取当前类和父类的某个公有属性
Field ageField = programMonkey.getClass().getField("mAge");
LogE(" age is : " + ageField.getName());
LogE(3);
//为属性设置值
ageField.set(programMonkey, 3322);
LogE("age is :" + programMonkey.getmAge());
LogE(4);
// 获取当前类的所有属性中的一个
Field mName = Person.class.getDeclaredField("mName");
mName.setAccessible(true);
Person person = new Person("wa", "fe", 888);
mName.set(person, "幻影旅团");
LogE("hy name:" + mName.get(person));
} catch (Exception e) {
e.printStackTrace();
}
}
获取类中的静态属性
public void getStaticFinalProperty() {
try {
Class<?> cla = Person.class;
LogE(1);
//getField()方法只能得到public的属性,getDeclaredField()方法得到所有直接写在class中的属性
//获取private static final 属性
Field gfField = cla.getDeclaredField("G_F");
gfField.setAccessible(true);
//java中的反射方法,Android中用不到,和java稍有不同
// Field modifiersField = Field.class.getDeclaredField("modifiers");
// modifiersField.setAccessible(true);
// modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
gfField.set(null, 99999);//第一个参数是所属的类,因为G_F是类参数,所以传null或者Person.class
LogE("final field:" + gfField.get(cla));//参数为所属的实体
LogE(2);
//获取private static 属性
Field lField = cla.getDeclaredField("L");
lField.setAccessible(true);
lField.set(null, "L_la_L");
LogE("L is:" + lField.get(cla));
} catch (Exception e) {
e.printStackTrace();
}
}
获取父类的构造方法
private void getSuperClass() {
Class<?> cla = ProgramMonkey.class;
while (cla != null) {
LogE("programMonkey's super class is:" + cla.getName());
cla = cla.getSuperclass();
}
}
获取接口及接口中的方法
private void getInterfaces() {
Class<?> cla = ProgramMonkey.class;
Class<?>[] interfacees = cla.getInterfaces();
for (Class<?> c : interfacees) {
LogE("programMonkey's interface is:" + c.getName());
//遍历接口中的方法
for (Method m : c.getDeclaredMethods()) {
LogE("interface method:" + m.getName());
}
}
}
获取构造函数并实例化,无视访问权限
private void getConstructor() {
Class<?> cls = Person.class;
try {
//构造方法的参数要填全,不管是否private都管用
Constructor<?> constructor = cls.getDeclaredConstructor(String.class, String.class, int.class);
//获取private函数的访问权限
constructor.setAccessible(true);
LogE(1);
LogE("constructor's name:" + constructor.getName());
LogE(2);
//实例化Person
Person newPerson = (Person) constructor.newInstance("pepelu", "kick ass", 233);
LogE("new person name:" + newPerson.getmName());
} catch (Exception e) {
e.printStackTrace();
}
}
LogE
private void LogE(int msg) {
Log.e("Reflection", "============== " + msg + "============== ");
}
private void LogE(String msg) {
Log.e("Reflection", "=== " + msg);
}
参考:
深入浅出反射
java反射机制详解 及 Method.invoke解释
从Java反射机制到Android注解框架
Java 反射基础(上)
Java 反射基础(下)