1-1-5 反射(重要)

说明:本文是校招复习系列文章,参考文献做统一说明!
整体目录详见:校招复习目录
另参考:
Java基础之—反射(非常重要)
大白话说Java反射
深入分析Java方法反射的实现原理

1. 反射介绍

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

反射机制实际上就是上帝模式,如果说方法的调用是 Java 正确的打开方式,那反射机制就是上帝偷偷开的后门,只要存在对应的class,一切都能够被调用。

2. 反射原理

img

3. 获取Class对象的三种方式

使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码)

如果我们动态获取到这些信息,我们需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。Java 提供了两种方式获取 Class 对象:

  1. 知道具体类的情况下可以使用:

    需要导入类的包

    	// Class alunbarClass = TargetObject.class;
        Class stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);
    
  2. 对象.getClass:

    第一种对象都有了还要反射干什么 ?

        Student stu1 = new Student();//new 产生一个Student对象,一个Class对象。
        Class stuClass = stu1.getClass();//获取Class对象
        System.out.println(stuClass.getName());
    
  3. 通过 Class.forName()传入类的路径获取,常用

    	// Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");
    	//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
    	Class stuClass3 = Class.forName("fanshe.Student");
    	System.out.println(stuClass3 == stuClass2);
    
  4. 实例-1:

    // 获取class
    Class<?> demo2 = Class.forName("jstudy.basic.Demo2");

    // 创建实例
    Object o = demo2.newInstance();

    // 获取方法集合
    Method[] me = demo2.getDeclaredMethods();
    for (Method m:me){
        System.out.println(m);
    }
    // 找到某一个方法,但是怎么去使用,这是一个问题?
    Method testForNum = demo2.getDeclaredMethod("testForNum");

实例-2:

在未运行时就已经确定了要运行的类(Apple) ,

    Apple apple = new Apple(); //直接初始化,「正射」
    apple.setPrice(4);

在运行时通过字符串值才得知要运行的类(com.chenshuyi.reflect.Apple)。所以反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

    Class clz = Class.forName("com.chenshuyi.reflect.Apple");
    Method method = clz.getMethod("setPrice", int.class);
    
	Constructor constructor = clz.getConstructor();
	Object object = constructor.newInstance();
	// 利用 invoke 方法调用方法
    method.invoke(object, 14); //存进去

	Method getPriceMethod = clz.getMethod("getPrice");
	// 利用 invoke 方法调用方法
	System.out.println("Apple Price:" + getPriceMethod.invoke(appleObj));

4. 静态编译和动态编译

  • 静态编译: 在编译时确定类型,绑定对象
  • 动态编译: 运行时确定类型,绑定对象

​ 两者的区别在于,动态编译可以最大程度地支持多态,而多态最大的意义在于降低类的耦合性,因此反射的优点就很明显了:解耦以及提高代码的灵活性。

5. 反射机制的优缺点

  • 优点: 运行期类型的判断,动态加载类,提高代码灵活度。
  • 缺点:
    • 性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的 java 代码要慢很多。
    • 安全问题:让我们可以动态操作改变类的属性同时也增加了类的安全隐患。

6. 反射的应用场景

反射是框架设计的灵魂。

在我们平时的项目开发过程中,基本上很少会直接使用到反射机制,但这不能说明反射机制没有用,实际上有很多设计、开发都与反射机制有关。例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架也大量使用到了反射机制。

举例:

  1. 我们在使用 JDBC 连接数据库时使用 Class.forName()通过反射加载数据库的驱动程序;利用反射将数据库的表字段映射到java对象的getter/setter方法;
  2. Spring 框架的 IOC(动态加载管理 Bean)创建对象以及 AOP(动态代理)功能都和反射有联系;
  3. 动态配置实例的属性;
  4. 反编译:.class–>.java
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值