Java基础之反射

Java基础之反射

一、什么是反射?

许多关于反射的讲解都是,在运行状态中,对于任意一个类,能知道他们的属性、构造方法、成员方法。对于任意一个对象,还能调用里面的一切方法和属性。假如有程序员A和程序员B,A想调用B写的类,但是B还没完成,A可以通过反射来修改或者查看B写的类有什么并且可以调用

二、反射是怎样实现的?

首先,必须获取Class字节码对象,用于表示.class文件,然后再解剖,解剖用的就是Class类中的方法,那有人可能要问了,为什么我不直接实例化一个对象来获取里面的信息呢,为什么要先获取Class对象,这不是麻烦吗?

三、反射与实例化对象的主要区别

1.运行时和编译时:反射是在运行时获取类信息和操作的机制,通过反射,我们可以不知道类的结构就对类进行查看以及一些操作,创建类的实例,调用方法,修改属性等,而直接实例化对象是在已知类的结构下完成的一些操作,在编译时就已经确定类的结构

2.灵活性与性能:反射可以动态地创建对象,调用方法等,但是性能较低,以为是在运行时期解析类信息,而直接实例化对象性能较高,因为它遵循正常的类加载和实例化流程

3.安全性:因为反射可以访问类的私有信息,这可能会破坏封装,而实例化对象只能允许访问公共方法

4.使用场景:反射大多数用在框架开发、动态代理等场景,而实例化对象说面向对象编程中最常用的方法

四、反射的常用方法

4-1、获取Class对象的三种方法

ublic class MyReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /**
         *
         * 获取class对象的三种方式
         * 1.Class.forName("全类名")
         * 2.类名.class
         * 3.对象.getClass()
         */

        //1.第一种方式
        //全类名:包名 + 类名
        Class clazz1 = Class.forName("com.wjk.MyReflect1.Student");

        //2.第二种方式
        Class<Student> clazz2 = Student.class;

        //3.第三种方式
        Student s = new Student();
        Class<? extends Student> clazz3 = s.getClass();

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz2 == clazz3);
    }


}

其中第一种是最常用的

4-2、Class类中用于获取构造方法的方法

public class MyReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        /**
         * Class类中用于获取构造方法的方法
         *      Constructor<?>[] getConstructors()
         *      Constructor<?>[] getDeclaredConstructors()
         *      Constructor<?>[] getConstructor(Class<?>...parameterTypes)
         *      Constructor<?>[] getDeclaredConstructor(Class<?>...parameterTypes)
         *
         *
         *      Constructor类中用于创建对象的方法
         *              T newInstance(Object... initargs)
         *              setAccessible(boolean flag)
         */

        //1.创建Class对象
        Class clazz = Class.forName("com.wjk.MyReflect2.Student");
        //2.获取所有构造方法
        //2-1.获取所有的公共构造方法
//        Constructor[] con1 = clazz.getConstructors();
//        for (Constructor constructor : con1) {
//            System.out.println(constructor);
//        }
//        System.out.println("------------------------");
//        //2-2获取所有构造方法,包括私有
//        Constructor[] con2 = clazz.getDeclaredConstructors();
//        for (Constructor constructor : con2) {
//            System.out.println(constructor);
//        }

        Constructor con1 = clazz.getDeclaredConstructor();
        System.out.println(con1);

        Constructor con2 = clazz.getDeclaredConstructor(String.class);
        System.out.println(con2);

        Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class);

        //3.获取权限修饰符
        //public:1,private:2,protected:4,static:8
        int modifiers = con3.getModifiers();
        System.out.println(modifiers);

        //在idea的底层用到了反射,根据权限修饰符判断修饰符类型,如果是私有的就不让你用

        //4.获取参数
        Parameter[] parameters = con3.getParameters();
        for (Parameter parameter : parameters) {
            System.out.println(parameter);
        }

        //创建对象
        Student stu = (Student) con3.newInstance("wjk", 21);
        System.out.println(stu);
        //为什么报错?因为这个权限修饰符是私有的,DeclaredConstructor只是让我看见这个私有的构造方法啊,但不能直接使用
        //如果要使用,必须setAccessible(true)
        //暴力反射:表示临时取消权限校验
        con3.setAccessible(true);


    }
}

暴力反射:临时取消权限校验,因为是私有的,所以让他临时变成不是私有

4-3、Class类中用于获取成员变量的方法

public class MyReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        /**
         * Class类中用于获取成员变量的方法
         *      Field[] getFields():返回所有公共成员变量对象的数组
         *      Field[] getDeclaredFields():返回所有成员变量对象的数组
         *      Field[] getField(String name):返回单个公共成员变量对象的数组
         *      Field[] getDeclaredField(String name):返回单个成员变量对象的数组
         *
         * Field类中用于创建对象的方法
         *      void set(Object,Object value):赋值
         *      Object get(Object obj):获取值
         */
        //1.获取Class字节码文件的对象
        Class<?> clazz = Class.forName("com.wjk.MyReflect3.Student");

        //2.获取单个成员变量的值
        Field name = clazz.getDeclaredField("name");

        //3.获取权限修饰符
        int modifiers = name.getModifiers();

        //4.获取成员变量的名字
        String n = name.getName();
        System.out.println(n);

        //5.获取成员变量的数据类型
        Class<?> type = name.getType();

        //6.获取成员变量记录的值
        Student s = new Student("wjk",21);

        //暴力反射
        name.setAccessible(true);
        String value = (String) name.get(s);
        System.out.println(value);

        //修改成员变量对象里面的值
        name.set(s,"lisi");

    }
}
  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值