前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TIII-Android技术篇之反射

TIII-Android技术篇之反射

作者头像
张风捷特烈
发布2018-09-29 11:24:58
4350
发布2018-09-29 11:24:58
举报

对于一个类来说,最重要的是什么?

代码语言:javascript
复制
构造+属性+方法+访问权限
待测试的类
代码语言:javascript
复制
/**
 * 作者:张风捷特烈
 * 时间:2018/5/6:10:40
 * 邮箱:1981462002@qq.com
 * 说明:反射测试类
 */
public class Person {
    private int age;
    private String name;
    private boolean isMan;
    public String address="beijing";

    public Person() {
        System.out.println("空参构造执行...");
    }

    public Person( String name, int age,boolean isMan) {
        this.age = age;
        this.name = name;
        this.isMan = isMan;
        System.out.println("三参构造执行...");

    }

    public void publicShow() {
        System.out.println("I am " + name + ",I " + age + "years");
    }

    public static void staticShow() {
        System.out.println("staticShow");
    }


    private void privateShow() {
        System.out.println("I am " + name + ",I " + age + "years");
    }

    public void paramShow(String str,int num) {
        System.out.println("I am " + str + ",I " + num + "years");
    }
}

一、拿到Class对象

Class对象是什么?

代码语言:javascript
复制
Class是一个类,而且它只有一个私有的构造函数,说明它不能通过new来获取对象,构造函数传入一个ClassLoader。
每个类被加载进入内存之后,系统就会为该类生成一个对应的java.lang.Class对象,
通过该Class对象就可以访问到JVM中的这个类,就可以获取某类的一切

private Class(ClassLoader loader) {
    // Initialize final field for classLoader.  The initialization value of non-null
    // prevents future JIT optimizations from assuming this final field is null.
    classLoader = loader;
}
1.对象.getClass()获取Class对象

前提:已存在对象,未知该类全貌,可以使用此方法获取Class对象来探测该类

代码语言:javascript
复制
Object类中有一个native方法获取Class
public final native Class<?> getClass();
代码语言:javascript
复制
    public static void getClass_1() {
        Person person = new Person();
        Class<? extends Person> personClass = person.getClass();
    }
2.类名.class获取Class对象

前提:需要已知类名

代码语言:javascript
复制
public static void getClass_2() {
    Class<Person> personClass = Person.class;
}
3.通过指定字符串:获取Class对象

前提:需已知全类名

代码语言:javascript
复制
public static void getClass_3() {
    try {
        Class<?> person = Class.forName("top.toly.bean.Person");
     System.out.println(person);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

二、通过反射构造对象
1.获取无参构造实例化对象:clazz.newInstance()
代码语言:javascript
复制
/**
 * 通过反射建无参实例
 */
public static void createInstance() {
    //早期:new 的时候,先根据类名寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
    // 再创建该字节码文件对相应的Person对象
    try {
        String className = "top.toly.bean.Person";
        // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
        Class<?> clazz = Class.forName(className);
        Object instance = clazz.newInstance();
        System.out.println(instance instanceof Person);//true
    } catch (Exception e) {
        e.printStackTrace();
    }
2.通过反射建有参实例:clazz.getConstructor
代码语言:javascript
复制
 /**
  * 通过反射建有参实例
  */
 private static void createInstance_2() {
     try {
         String className = "top.toly.bean.Person";
         // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
         Class<?> clazz = Class.forName(className);
         Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
         Object instance = constructor.newInstance("捷特", 24, true);
         System.out.println(instance);
         //Person{age=24, name='捷特', isMan=true, address='beijing'}
     } catch (Exception e) {
         e.printStackTrace();
     }
 }
补充:XXXDeclaredXXX都是只获取本类,不包括父类
代码语言:javascript
复制
// 获得该类所有的构造器,不包括其父类的构造器
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
// 获得该类所以public构造器,包括父类 
public Constructor<T> getConstructor(Class<?>... parameterTypes)

三、通过反射获取字段
1.获取公共字段:clazz.getField
代码语言:javascript
复制
/**
 * 获取公共字段
 */
public static void getPublicField() throws Exception {
    String className = "top.toly.bean.Person";
    // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
    Class<?> clazz = Class.forName(className);
    Field address = clazz.getField("address");//获取公有字段
    Object o = address.get(clazz.newInstance());
    System.out.println(o);//beijing
}
2.获取私有字段:
代码语言:javascript
复制
/**
 * 获取私有字段
 */
public static void getPrivateField() throws Exception {
    String className = "top.toly.bean.Person";
    // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
    Class<?> clazz = Class.forName(className);
    Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
    Object instance = constructor.newInstance("捷特", 24, true);
    //可以获取所有类型字段
    Field name = clazz.getDeclaredField("age");
    //想要访问私有,需要将可获取置为true
    name.setAccessible(true);
    //设置私有成员值
    name.setInt(instance,30);
    //获取私有成员值
    Object o = name.get(instance);
    System.out.println(o);//30
}

四、调用方法:
1.获取公共方法:getMethods()
代码语言:javascript
复制
/**
 * 获取公共方法
 */
public static void getPublicMethod() throws Exception {
    String className = "top.toly.bean.Person";
    // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
    Class<?> clazz = Class.forName(className);
    //创建实例
    Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
    Object instance = constructor.newInstance("捷特", 24, true);
    Method[] methods = clazz.getMethods();//只能获取公有方法,包括父类
    for (Method m : methods) {
        System.out.println(m);
    }
    //获取公共无参
    Method publicShow = clazz.getMethod("publicShow", null);
    //调用函数:invoke
    publicShow.invoke(instance, null);
    //获取公共有参
    Method paramShow = clazz.getMethod("paramShow", String.class, int.class);
    paramShow.invoke(instance, "龙少", 24);
}

clazz.getDeclaredMethod:获取指定名称和参数类型的本类中声明(访问权限不限)的方法 clazz.getDeclaredMethods(): 获取该类所有的方法,不包括父类 clazz.getMethod:获取当前类及所有继承的父类的public修饰的方法。仅包括public clazz.getMethods();获取该类所有的public方法,包括父类的

2.获取私有方法:getDeclaredMethods()
代码语言:javascript
复制
/**
 * 获取私有方法
 */
public static void getPrivateMethod() throws Exception {
    String className = "top.toly.bean.Person";
    // 寻找到该类的字节码文件,并加载到内存,创建该字节码文件对象。
    Class<?> clazz = Class.forName(className);
    Method[] declaredMethods = clazz.getDeclaredMethods();//获取该类中的所有方法
    //创建实例
    Constructor<?> constructor = clazz.getConstructor(String.class, int.class, boolean.class);
    Object instance = constructor.newInstance("捷特", 24, true);
    for (Method m : declaredMethods) {
        System.out.println(m);
    }
    Method privateShow = clazz.getDeclaredMethod("privateShow", null);
    privateShow.setAccessible(true);
    privateShow.invoke(instance,null);
}

反射差不多也就这些,理论并不难,学以致用才是关键


后记、
1.声明:

[1]本文由张风捷特烈原创,转载请注明 [2]欢迎广大编程爱好者共同交流 [3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 [4]你的喜欢与支持将是我最大的动力

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.09.10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 待测试的类
  • 一、拿到Class对象
    • 1.对象.getClass()获取Class对象
      • 2.类名.class获取Class对象
        • 3.通过指定字符串:获取Class对象
        • 二、通过反射构造对象
          • 1.获取无参构造实例化对象:clazz.newInstance()
            • 2.通过反射建有参实例:clazz.getConstructor
              • 补充:XXXDeclaredXXX都是只获取本类,不包括父类
              • 三、通过反射获取字段
                • 1.获取公共字段:clazz.getField
                  • 2.获取私有字段:
                  • 四、调用方法:
                    • 1.获取公共方法:getMethods()
                      • 2.获取私有方法:getDeclaredMethods()
                      • 后记、
                        • 1.声明:
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档