2019-04-18

Java 反射干货解析

图示分析

图片.png

反射机制代码详解

定义:Person类

package reflex_01;

public class Person {
    private String name;
    public int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

定义:主类

package reflex_01;

public class ReflexDemo {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        String className="reflex_01.Person";
        //通过该类的名称,加载对应的字节码文件,并封装成字节码文件对象ca
        Class ca=Class.forName(className);//会抛出一个类不存在异常

        System.out.println(ca);

        //获取newInstance()可以创建字节码对象所表示的类的实例
        Object obj = ca.newInstance();
        /**
         * 通常被反射的类都会提供空参数的构造方法
         *  没有对应的构造方法   会报InstantiationException(实例化异常)
         *  如果有提供,但权限不够   会报IllegalAccessException (非法访问异常)
         */
        System.out.println(obj);

        /**
         * 底层原理:
         *      1.加载Person类,并将Person封装成字节码文件对象
         *      2.通过new创建Person对象
         *      3.调用构造方法对对象初始化
         *    Person p=new Person();
         */
    }
}

获取构造方法

package reflex_01;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class ReflexDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        String className="reflex_01.Person";
        //通过该类的名称,加载对应的字节码文件,并封装成字节码文件对象ca
        Class ca=Class.forName(className);//会抛出一个类不存在异常

        //获取指定的共有构造器    获取Person两个参数String int类型的构造方法
        Constructor cons = ca.getConstructor(String.class,int.class); // 此构造方法是私有的,因此无法访问NoSuchMethodException
        //获取共有的无参构造
    //    Constructor con = ca.getConstructor();

     //   Constructor cans1 = ca.getDeclaredConstructor(String.class, int.class);  //同样会有权限问题出现
        //有了构造器对象之后,可以用构造器对象来初始化类对象
         Object o = cons.newInstance("张三", 23);
     //   Object o = cans1.newInstance("张三", 23);

    //    Object o1 = con.newInstance();
    //    System.out.println(o1);     //Person{name='null', age=0}
        System.out.println(o);     //Person{name='张三', age=23}

    }

}

字段获取

package reflex_01;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class FieldGet {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        String className="reflex_01.Person";
        //通过该类的名称,加载对应的字节码文件,并封装成字节码文件对象ca
        Class ca=Class.forName(className);//会抛出一个类不存在异常

        //获取公共的字段   age  是public的
        Field field = ca.getField("age");

        //获取本类中已有的成员    name是私有的
        Field name = ca.getDeclaredField("name");

        Method method = ca.getMethod("getName");

        Method method1 = ca.getDeclaredMethod("setName", String.class);

        //总结: getXXX都是获取类中公共的成员
        //      getDeclaredXXX 获取本类中已有的成员  包括private修饰的成员方法及其变量
        //构造方法等其他字段权限如果出现问题,那么只能使用暴力访问,解除权限检查

        System.out.println(name);
        System.out.println(field);
    }

}

暴力访问机制

package reflex_02;

import java.lang.reflect.Field;

public class AxcessibleDemo {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchFieldException {
        String className="reflex_01.Person";
        //通过该类的名称,加载对应的字节码文件,并封装成字节码文件对象ca
        Class ca=Class.forName(className);

        Field field=ca.getDeclaredField("name" );
        //对其进行值的设置,必须先有对象
        Object obj = ca.newInstance();
        //通过查找父类的setAccessibleObject的方法  setAccessible(true);
        field.setAccessible(true);//取消权限检查  暴力访问

        field.set(obj,"流星雨");    //IllegalAccessException   name字段是私有的

        System.out.println(field.get(obj));

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