什么是反射

1.Oracle 官方对反射的解释是:
Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.
2.简而言之,通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
3.
(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

使用反射机制可以动态获取当前class的信息 比如方法的信息、注解信息、方法的参数、属性等;

反射机制的优缺点

第三方框架—创建对象 不是直接new 反射机制创建
目的:提供开发者能够更好封装框架实现扩展功能。

在一个类中 定义了一个私有属性/方法 反射机制破解私有属性

1、优点:在运行时获得类的各种内容,进行反编译,对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
(1)反射会消耗一定的系统资源,因此如果不需要动态地创建一个对象,那么就不需要用反射;
(2)反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题。

反射的用途:

反编译:.class–>.java
1.通过反射机制访问java对象的属性,方法,构造方法等
3. JDBC加载驱动连接 class.forname
Class.forName(“com.mysql.jdbc.Driver”); // 动态加载mysql驱动
4.Spring容器框架IOC实例化对象

  1. 自定义注解生效(反射+Aop)
  2. 第三方核心的框架 mybatis orm

反射技术的使用

Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量(成员变量也称为类的属性)
Method类 代表类的方法
Constructor类 代表类的构造方法
1.getField、getMethod和getCostructor方法可以获得指定名字的域、方法和构造器。
2.getFields、getMethods和getCostructors方法可以获得类提供的public域、方法和构造器数组,其中包括超类的共有成员。
3.getDeclatedFields、getDeclatedMethods和getDeclaredConstructors方法可以获得类中声明的全部域、方法和构造器,其中包括私有和受保护的成员,但不包括超类的成员。

反射常用的Api

(1)Object–>getClass
(2)任何数据类型(包括基本的数据类型)都有一个“静态”的class属性
(3)通过class类的静态方法:forName(String className)(最常用)
Class<?> aClass = Class.forName(“com.cc.entity.UserEntity”);

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        //获取源代码class,只会有一份。
        /**
         * 1方式一
         */
        Class<UserEntity> uClass = UserEntity.class;
        //默认无参构造
        UserEntity userEntity = uClass.newInstance();
        /**
         * 2方式二
         */
        Class<?> aClass = Class.forName("com.gtf.UserEntity");
        UserEntity userEntity1 = (UserEntity) aClass.newInstance();
        /**
         * 3方式三
         */
        UserEntity userEntity2 = new UserEntity();
        Class<? extends UserEntity> aClass1 = userEntity2.getClass();
    }

反射执行构造函数

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
        /**
         * 2方式二
         */
        Class<?> aClass = Class.forName("com.gtf.UserEntity");
//        //默认无参构造函数
//        UserEntity userEntity1 = (UserEntity) aClass.newInstance();
//        System.out.println(userEntity1);
//        //有参构造函数
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class, Integer.class);
        UserEntity gtf = (UserEntity) declaredConstructor.newInstance("gtf", 18);
        System.out.println(gtf);

    }

反射执行给属性赋值

反射执行给公有属性赋值

        /**
         * 2方式二
         */
        Class<?> aClass = Class.forName("com.gtf.UserEntity");
        UserEntity o = (UserEntity) aClass.newInstance();


        aClass.getDeclaredField("pubusername").set(o, "张三");
        System.out.println(o.getName());

反射执行调用方法

反射调用公有方法

 /**
         * 2方式二
         */
        Class<?> aClass = Class.forName("com.gtf.UserEntity");
        aClass.getMethod("setName", String.class).invoke(aClass.newInstance(), "gtf");
      /**
         * 2方式二
         */
        Class<?> aClass = Class.forName("com.gtf.UserEntity");
        aClass.getDeclaredMethod("setName", String.class).invoke(aClass.newInstance(), "gtf");

反射越过fan型jiancha

    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        ArrayList<String> strings = new ArrayList<>();
        strings.add("a");
        Class<? extends ArrayList> aClass = strings.getClass();
        Method add = aClass.getDeclaredMethod("add", Object.class);
        add.setAccessible(true);
        add.invoke(strings, 1);
        //如果越过fan形检查,则会报错。
        strings.forEach(System.out::println);
    }