美文网首页
Java基础之反射

Java基础之反射

作者: 沐左 | 来源:发表于2018-11-29 11:23 被阅读0次

    Java基础之—反射(非常重要)
    Java中反射机制详解
    Java进阶之reflection(反射机制)——反射概念与基础
    浅谈java反射机制

    • 功能说明类
    package zuo.com.javademo.bean;
    
    /**
     * Person实体类
     * @author zuo
     * @date 2018/9/18 21:55
     */
    public class Person {
        private int id;
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        private Person(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
    
        private int getAge() {
            return age;
        }
    
        private void setAge(int age) {
            this.age = age;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    

    反射的定义

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。


    API

    java 8 API

    反射涉及的类,除了Class类之外,基本上都在java.lang.reflect包里面,常用的类有Constructor,Field,Method类等,AccessibleObject类是前面三个类的基类,主要包含设置安全性检查等方法。

    reflect

    在类加载的时候,jvm(Java 虚拟机)会创建一个class对象(字节码对象)

    class对象(字节码对象)是可以说是反射中最常用的,获取class对象(字节码对象)的方式的主要有三种

    • 1、根据类名:类名.class
      当类被加载成.class文件时,此时Person类变成了.class,获取该字节码文件,也就是获取对象自己, 该类处于字节码阶段。
    Class clazz  = Person.class;    
    
    • 2、根据对象:对象.getClass()
      对象是类的实例,通过类的实例获取该类的字节码文件对象,该类处于创建对象的阶段
    Class clazz = p.getClass();    
    
    • 3、根据全限定类名:Class.forName(全限定类名)
      通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件(全限定类名 -- 即类的完整路径)。
    //Class clazz = Class.forName("全限定类名");
    Class clazz = Class.forName("zuo.com.javademo.bean.Person");
    
    • 测试
      测试结果

    类的构造函数

    当我们拿到一个类的构造函数之后,我们就可以轻易的创建类的对象了。常用的方法有:

    • 1、获取全部的构造函数
    Class aClass = Class.forName("zuo.com.javademo.bean.Person");
    Constructor[] constructors = aClass.getConstructors();
    
    • 2、获取指定的构造函数
      当我们知道目标类中的构造函数的参数时我们可以获取指定的构造函数。
    Class aClass = Class.forName("zuo.com.javademo.bean.Person");
    Constructor constructor = aClass.getConstructor(int.class,String.class);
    
    • 测试
        @Test
        public void constructorTest() throws Exception {
            Class aClass = Class.forName("zuo.com.javademo.bean.Person");
            Constructor[] constructors = aClass.getConstructors();
            for (int i = 0; i < constructors.length; i++) {
                Class<?> parameterTypesClass[] = constructors[i].getParameterTypes();
                System.out.print("第" + i + "个构造函数:\t (");
                for (int j = 0; j < parameterTypesClass.length; j++) {
                    System.out.print(parameterTypesClass[j].getName() + (j == parameterTypesClass.length - 1 ? "" : "\t"));
                }
                System.out.print(")\n");
            }
    
            Class bClass = Class.forName("zuo.com.javademo.bean.Person");
            Constructor constructor = bClass.getConstructor(int.class, String.class);
            Class<?> parameterTypesClass[] = constructor.getParameterTypes();
            System.out.print("指定构造函数:\t (");
            for (int j = 0; j < parameterTypesClass.length; j++) {
                System.out.print(parameterTypesClass[j].getName() + (j == parameterTypesClass.length - 1 ? "" : "\t"));
            }
            System.out.print(")\n");
        }
    
    测试结果

    类的方法

    获取类方法的相关方法


    获取类的方法
    Class aClass = Class.forName("zuo.com.javademo.bean.Person");
    
    • 1、获取指定的公有方法
    Method setId = aClass.getMethod("setId", int.class);
    
    • 2、获取所有公有的方法(包括父类的公有方法)
     Method[] methods = aClass.getMethods();
    
    • 3、获取当前类中声明的所有方法,包括私有方法,但不包括父类方法
    Method[] methods1 = aClass.getDeclaredMethods();
     //注意:只有取消安全性检查设置后才可以调用private修饰的方法,取消所有方法的安全性检测
    Method.setAccessible(methods1, true);
    
    • 4、获取声明方法中的指定方法

    获取私有无参方法

     Method getAge = aClass.getDeclaredMethod("getAge");
    //注意:只有取消安全性检查设置后才可以调用private修饰的方法,取消该方法的安全性检测
    getAge.setAccessible(true);
    

    获取私有有参方法

    Method setAge = aClass.getDeclaredMethod("setAge",int.class);
    //注意:只有取消安全性检查设置后才可以调用private修饰的方法,取消该方法的安全性检测
    setAge.setAccessible(true);
    
    • 5、调用获取的指定方法
    //调用方法,需要先获取类的对象
    Object person = aClass.newInstance();
    //调用setAge方法,使用Method 的 invoke方法,需要传入类的对象和方法的参数
    Object back = setAge.invoke(person, 25);
     //因为setAge方法的返回类型为 void 所以 back = null
    int age = (int) getAge.invoke(person);
    //getAge方法的返回类型为 int ,我们用 int 来接收一下 , 因为之前调用来 setAge ,所以我们获取到的 age=25
    

    此时person 对象 :Person{id=0, name='null', age=25}

    • 6、调用构造函数获取对象
    Constructor constructor = aClass.getConstructor(int.class, String.class);
    Object instance = constructor.newInstance(2, "迈克尔");
    

    通过构造函数获取的对象:Person{id=2, name='迈克尔', age=0}

    测试结果

    类的属性

    1、getFields():获取所有的"公有字段"
    
    2、getDeclaredFields():获取所有字段,包括:私有、受保护、默认、公有;
    
    3、getField(String fieldName):获取某个"公有的"字段;
    
    4、getDeclaredField(String fieldName):获取某个字段(可以是私有的);
    
    5、public void set(Object obj,Object value);设置字段的值
    参数说明:
     *obj:要设置的字段所在的对象;
     *value:要为字段设置的值;
    
    6、获取对应字段的值
    get(Object obj);  //obj:要设置的字段所在的对象;
    ------
     Class<?> buildconfig = Class.forName("com.kingoit.yzt.BuildConfig");
    String flavor = String.valueOf(buildconfig.getField("FLAVOR").get(buildconfig));
    

    相关文章

      网友评论

          本文标题:Java基础之反射

          本文链接:https://www.haomeiwen.com/subject/eqcvnftx.html