java反射

看了张明云的博客,稍微总结一下,例子还是用他的

方法、属性的归属问题,属于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

反射方法封装库

https://github.com/jOOQ/jOOR

父类: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 反射基础(下)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容