反射浅析

  • 普通的开发流程是已知对象来获取属性
  • 而反射的流程是——已知属性来获取对象
但我认为反射本身比较抽象

可能是我一开始学Java基础没打好的原因,在学习到框架的时候。就感觉很吃力,学习流于形式。知其然,但不知其所以然。忘的比学的快。到最后还是得反过来啃下反射这块硬骨头。

反射机制

  1. 反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到
  2. 加载完类之后,在堆中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个Class对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射
  • p对象--》类型Person类
  • Class对象cls --->类型Class类
如果只是简单的了解反射有什么用,最常见的其实就两个
  • 根据类名创建实例(类名可以从配置文件读取,不用new,达到解耦)
  • 用Method.invoke执行方法

下面java代码的全部流程,我将大体的给大家理顺一下
image
image

反射在哪里执行?

其中反射就英语在加载阶段与运行阶段之间

直观展示,上代码,走cmd!

import java.lang.reflect.Method;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Scanner scanner = new Scanner(System.in);
        System.out.printf("请输入key");
        String key = scanner.next();
        switch (key) {
            case "1":
                Dog dog = new Dog();//静态加载,依赖性很强
                dog.cry();
                break;
            case "2":
                //反射->动态加载
                Class cls = Class.forName("Cat"); //加载Person类[动态加载]
                Object o = cls.newInstance();
                Method m = cls.getMethod("hi");
                m.invoke(o);
                System.out.println("ok ");
                break;
            default:
                System.out.println("do nothing..");
        }
    }
}


class Dog {
    public void cry() {
        System.out.printf("汪汪汪");
    }
}

因为new Dog()是静态加载,因此必须编写Dog
Cat类是动态加载,所以,没有编写Cat类也不会报错,只有当动态加载该image类时,才会报错

imageimage

出现class类说明编译成功

结果如下 说明

image
我们再追加Cat类的相关信息

class Cat {
    public void hi() {
        System.out.printf("喵喵喵");
    }
}

编译 运行

image

All in all

1.静态加载:编译时加载相关的类,如果没有则报错,依赖性太强

2.动态加载:运行时加载需要的类,如果运行时不用该类,即使不存在该类,则不报错,降低了依赖性


反射技术

反射的基本的概念

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

反射技术应用的场景

  1. JDBC加载驱动连接 class.forname

  2. Spring容器框架IOC实例化对象

  3. 自定义注解生效(反射+Aop)

  4. 第三方核心的框架

反射技术的使用

Class类 代表类的实体,在运行的Java应用程序中表示类和接口

Field类 代表类的成员变量(成员变量也称为类的属性)

Method类 代表类的方法

Constructor类 代表类的构造方法

使用反射机制初始化对象 获取当前class的信息

Class aClass = Class.forName("com.mayikt.entity.UserEntity");

执行无参数构造函数

Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity"); 
UserEntity userEntity = (UserEntity) aClass.newInstance(); 
userEntity.setName("mayikt"); 
userEntity.setUserId(1234); 
System.out.println(userEntity);

执行有参数构造函数

Class\<?>  aClass = Class.forName("com.mayikt.entity.UserEntity"); // 执行有参数构造函数 
Constructor<?> constructor = aClass.getConstructor(Integer.class, String.class); 
UserEntity userEntity = (UserEntity) constructor.newInstance(10, "mayikt"); 
System.out.println(userEntity);     

使用反射机制给属性赋值

Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity"); // 给私有属性赋值
UserEntity  userEntity = (UserEntity) aClass.newInstance(); 
Field userId = aClass.getDeclaredField("userId"); 
userId.setAccessible(true); userId.set(userEntity,12); 
Field name = aClass.getDeclaredField("name"); 
name.setAccessible(true); 
name.set(userEntity,"mayikt"); 
System.out.println(userEntity);   

  • Exception in thread "main" java.lang.IllegalAccessException: Class com.mayikt.Test001 can not access a member of class com.mayikt.entity.UserEntity with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)

如果使用反射给私有属性或者调用私有的方法 都需要设置权限

使用反射机制给调用方法

Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity"); // 给私有属性赋值 
UserEntity  userEntity = (UserEntity) aClass.newInstance(); 
Method meite = aClass.getDeclaredMethod("meite", Integer.class);
meite.setAccessible(true); //这一步 暴力反射
Object invoke = meite.invoke(userEntity, 10); S
ystem.out.println(invoke);
posted @ 2021-06-12 21:49  飞飞很要强  阅读(63)  评论(0编辑  收藏  举报