Java 的作用
反射通常由程序使用,这些程序需要能够检查或修改在Java 虚拟机 中运行的应用程序的运行时行为,这是一个相对高级的功能,只有那些掌握了语言基础知识的开发人员才能使用。考虑到这一点,反射是一种强大的技术,可以使应用程序执行本来不可能的操作。
1. 可扩展性
应用程序可以通过使用完全限定名称创建可扩展性对象的实例来使用外部的用户定义类。
2. 类浏览器和可视化开发环境
类浏览器需要能够枚举类的成员。可视化开发环境可以从利用反射中可用的类型信息中受益,以帮助开发人员编写正确的代码。
3. 调试器和测试工具
调试器需要能够检查类上的私有成员。测试工具可以利用反射系统地调用类上定义的可发现的set API,以确保测试套件中的高级代码覆盖率。
反射的缺点
反射是强大的,但不应随意使用。如果可以在不使用反射的情况下执行操作,则优选避免使用它。通过反射访问代码时,应牢记以下问题。
1. 绩效开销
由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化。因此,反射操作的性能低于非反射操作,并且应避免在性能敏感应用程序中频繁调用的代码段中。
2. 安全限制
反射需要运行时权限,在安全管理器下运行时可能不存在。对于必须在受限安全上下文中运行的代码,例如在Applet中,这是一个重要的考虑因素。
3. 内部接触
由于反射允许代码执行在非反射代码中非法的操作,例如访问private字段和方法,因此使用反射会导致意外的副作用,这可能导致代码功能失常并可能破坏可移植性。反射代码打破了抽象,因此可能会通过升级平台来改变行为。
类反射方法
获取 Class 对象
Object.getClass()
.class语法
原始类型不能使用Object.getClass()方法获得Class对象
Class.forName()
如果可以得到类的全称可以使用该方法获取Class对象
基本类型的包装类TYPE静态变量
其他返回Class对象的方法
Class.getSuperclass()
Class.getClasses() 返回作为类成员的所有公共类,接口和枚举,包括继承的成员。
Class.getDeclaredClasses() 返回在此类中显式声明的所有类接口和枚举。
Class.getDeclaringClass() 返回在此类成员变量声明的类,匿名类没有DeclaringClass,但是有EnclosingClass
java. lang .reflect.Field.getDeclaringClass()
java.lang.reflect.Method.getDeclaringClass()
java.lang.reflect.Constructor.getDeclaringClass()
Class.getEnclosingClass() 返回类的直接封闭类。
检查类修饰符和类型
Class.getModifiers()方法获取修饰符和类型 可以使用一个或多个影响其运行时行为的修饰符声明一个类:
public, protected, and private
abstract
static
final
strictfp
Annotations
获取类的成员
获取成员变量
Class API列表返回值?继承成员?私有成员?getDeclaredField()nonoyesgetField()noyesnogetDeclaredFields()yesnoyesgetFields()yesyesno
获取成员方法
Class API列表返回值?继承方法?私有方法?getDeclaredMethod()nonoyesgetMethod()noyesnogetDeclaredMethods()yesnoyesgetMethods()yesyesno
构造方法
Class API列表返回值?继承方法?私有方法?getDeclaredConstructor()noN/A1yesgetConstructor()noN/A1nogetDeclaredConstructors()yesN/A1yesgetConstructors()yesN/A1no
故障排除
警告报错:Compiler Warning: “Note: … uses unchecked or unsafe operations”
构造函数 不可访问时的InstantiationException
成员
Fields
获取字段类型
Field.getType():获取字段的类型
Field.getGenericType():获取字段的泛型类型
检索和解析字段修饰符
Field.getModifiers():获取字段修饰符
Field.isSynthetic():判断字段是否为合成的
Field.isEnumConstant():判断字段是否为枚举
获取和设置字段值
Field.set*() :获取字段值
Field.get*() :设置字段值
故障排除
IllegalArgumentException due to Inconvertible Types
NoSuchFieldException for Non-Public Fields
IllegalAccessException when Modifying Final Fields
Methods
获取方法类型信息
Method.toGenericString()
Method.getReturnType()
Method.getGenericReturnType()
Method.getParameterTypes()
Method.getGenericParameterTypes()
Method.getExceptionTypes()
Method.getGenericExceptionTypes()
获取方法参数的名字
Method.getParameters():获取方法参数
Parameter.getType():获取参数类型
Parameter.getName():获取参数名称
Parameter.Modifiers():获取参数修饰符
Parameter.isImplicit():true如果在源代码中隐式声明此参数
Parameter.isNamePresent():true如果参数根据.class文件具有名称
Parameter.isSynthetic():true如果在源代码中既未隐式声明也未显式声明此参数
检索和解析方法修饰符
Method.getModifiers():获取方法修饰符
Method.isSynthetic():返回true此可执行文件是否为合成构造
Method.isVarArgs():返回true如果这个可执行文件被宣布为带有可变数量的参数
Method.isBridge():true如果此方法是桥接方法
调用方法
Method.invoke():调用方法
故障排除
NoSuchMethodException Due to Type Erasure
IllegalAccessException when Invoking a Method
IllegalArgumentException from Method.invoke()
InvocationTargetException when Invoked Method Fails
Constructors
获取构造函数
检索和解析构造函数修饰符
Constructor.getModifiers()
创建一个新实例
Constructor.newInstance():优先使用
Class.newInstance()
故障排除
InstantiationException Due to Missing Zero-Argument Constructor
Class.newInstance() Throws Unexpected Exception
Problems Locating or Invoking the Correct Constructor
IllegalAccessException When Attempting to Invoke an Inaccessible Constructor
数组和 枚举类型
数组
识别数组类型
Class.isArray()
创建新数组
Array.newInstance()
获取和设置数组及其组件
Array.set*()
Array.get()
故障排除
IllegalArgumentException due to Inconvertible Types
ArrayIndexOutOfBoundsException for Empty Arrays
IllegalArgumentException if Narrowing is Attempted
枚举
识别枚举类型
Class.isEnum():枚举无法通过反射实例化,枚举常量是唯一的
Class.getEnumConstants()
Field.isEnumConstant()
使用枚举类型获取和设置字段
Field.set()
Field.get()
故障排除
IllegalArgumentException When Attempting to Instantiate an Enum Type
IllegalArgumentException when Setting a Field with an Incompatible Enum Typc