请选择 进入手机版 | 继续访问电脑版

湖南新梦想

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 62|回复: 0

反射

[复制链接]

37

主题

37

帖子

155

积分

注册会员

Rank: 2

积分
155
发表于 2023-3-16 20:31:55 | 显示全部楼层 |阅读模式

什么是反射
反射(Reflection)是 Java 的特性之一,它可以让运行中的 Java 程序获取自身的信息,并且可以操作类或者对象的内部属性。
反射的核心是 JVM 在运行时才会动态加载类、调用方法和访问属性,它不需要在编译期知道运行的对象是谁。
Java 反射主要提供以下的功能:
  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法

反射的主要用途
  • 实现工厂模式和代理模式等设计模式。
  • JDBC 的数据库连接。
  • Spring、Struts 等框架,使用反射在运行时动态加载需要加载的对象。
  • IDE 开发工具的提示,比如当我们输入一个对象或类并想调用它的属性或方法时,一按点号,编译器就会自动列出它的属性或方法

反射的优缺点
优点:
  • 可以在运行期对类型进行判断,动态类加载等操作。
  • 提高代码的灵活度。例如:JDBC 可以动态连接数据库。

缺点:
  • 性能问题
    因为反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些直接调用慢的多。所以尽量避免在经常被执行的代码或者对性能要求很高的程序中使用反射。
    (反射大概比直接调用慢 50 ~ 100 倍,但是需要在执行 100 万遍的时候才会有所感觉)
  • 安全限制
    使用反射技术要求程序必须在一个没有安全限制的环境中运行。
  • 内部暴漏
    反射允许代码执行一些在正常情况下不被允许的操作(访问私有的属性或方法),所以使用反射可能会导致意料之外的副作用 —— 代码有功能上的错误,降低可移植性。反射破坏了代码的抽象性,因此当平台发生改变的时候,代码的行为就可能也随着变化。

提问:Java 反射可以访问和修改私有成员变量,那封装成 private 还有意义么?
既然小偷可以访问和搬走私有成员家具,那封装成防盗门还有意义么?这是一样的道理,并且 Java 从应用层给我们提供了安全管理机制——安全管理器,每个 Java 应用都可以拥有自己的安全管理器,它会在运行阶段检查需要保护的资源的访问权限及其它规定的操作权限,保护系统免受恶意操作攻击,以达到系统的安全策略。
所以其实反射在使用时,内部有安全控制,如果安全设置禁止了这些,那么反射机制就无法访问私有成员。
具体使用1.4.1 Class1.4.1.1 获取 Class
那我们如何获取想要的 Class,look this Code
获取 Class 的三种方法
  • getClass()
  • T.class
  • Class.forName

获取父类 Class
通过 getSuperclass() 方法获取父类的 Class
Field1.4.2.1 获取 Field
如何通过 Class 实例获取字段信息。Class 类提供了以下几个方法来获取字段:
  • Field getField(String name):根据字段名获取某个 public 的 field
  • Field[] getFields():获取所有 public 的 field
  • Field getDeclaredField(String name):根据字段名获取当前类的某个 field
  • Field[] getDeclaredFields():获取当前类的所有 field

获取 Field 的信息
一个 Filed 对象包含了一个字段的所有信息:
  • getName():返回字段名称,例如:name;
  • getType():返回字段类型,也是一个 Class 实例,例如:String.class
  • getModifiers():返回字段的修饰符,它是一个 int,不同的 bit 表示不同的含义。

获取字段值
我们拿到了 Field,该通过 Field 获取该字段对应的值。我们还是用上面的例子来获取 name 值。
在自己的类里访问的,就是你私有的(private),可以随便访问--getDeclaredField,
在其他类访问 私有 变量时 需要手动设置 (setAccessible(true)) 才可以访问   否则会报错
Exception in thread "main" java.lang.IllegalAccessException: Class com.javastudy.reflection.Fields.FieldTest4 can not access a member of class com.javastudy.reflection.Fields.Animal with modifiers "private"1.4.2.4 设置字段值
通过 Field 实例既能获取指定实例的字段值,也可以设置字段的值。
设置字段值通过 Field 的 set 方法实现。
小结
Java 的反射 API 提供的 Field 类封装了字段的所有信息:
  • 通过 Class 实例获取 Field 实例的方法:getField(String name),getFields(),getDeclaredField(),getDeclaredFields()
  • 通过 Field 实例获取字段信息的方法:getName(),getType(),getModifiers()
  • 通过 Field 实例可以读取或者设置某个对象的字段,如果存在访问限制,首先要调用 setAccessible(true),再访问非 public 字段。

获取 Method
通过 Class 实例获取所有 Method 的信息,Class 类提供了以下几个方法来获取方法:
  • Method getMethod(name, parameterTypes):根据方法名和参数类型获取某个 public 的 Method
  • Method[] getMethods():获取所有 public 的 Method
  • Method getDeclaredMethod(name, parameterTypes):根据方法名和参数获取当前类的某个 Method
  • Method[] getDeclaredMethods():获取当前类的所有 Method

获取 Method 的信息
一个 Method 对象包含了一个方法的所有信息:
  • getName():返回方法名称,例如:getScore
  • getReturnType():返回方法的返回值类型,是一个 Class 实例,例如:String.class
  • getParameterTypes():返回方法的参数类型,是一个 Class 数组,例如:{String.class, int.class}
  • getModifiers():返回方法的修饰符,和 Field 的 getModifiers() 大同小异


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|湖南新梦想 ( 湘ICP备18019834号-2 )

GMT+8, 2023-3-24 18:33 , Processed in 0.038974 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表