《Java核心技术 卷I》学习笔记23:反射

本文详细介绍了Java反射机制,包括Class类的使用、异常处理、动态创建对象、访问和修改对象字段、创建泛型数组以及调用任意方法。通过反射,可以在运行时分析和操作类、对象,实现更灵活的代码编写。
摘要由CSDN通过智能技术生成


能够分析类能力的程序称为 反射。反射机制的功能有:

  1. 在运行时分析类的能力。
  2. 在运行时检查对象。例如,编写一个适用于所有类的toString方法。
  3. 实现泛型数组操作代码。
  4. 利用Method对象。

1 Class类

在程序运行期间,Java运行时系统始终为所有对象维护一个运行时类型标识,这些信息会跟踪每个对象所属的类,虚拟机利用运行时类型信息选择要执行的正确的方法。Class类用于保存这些信息。

Object类中的getClass方法返回一个Class类型的实例,Class类中的getName方法返回类名,这两个方法结合起来可以用来获得类名。如果类在一个包里,包名也会作为类名的一部分。例如:

Employee e;
System.out.println(e.getClass().getName());

Class中的静态方法forName可以获得类名对应的Class对象,它的签名和用法如下:

/* 签名 */
static Class forName(String className)
/* 用法 */
String className = "java.util.Random";
Class cl = Class.forName(className);

如果类名保存在一个字符串中,这个字符串会在运行时变化,就可以使用这个方法在运行时获得不同的Class对象。如果className是一个类名或接口名,这个方法可以正常执行;否则,将抛出一个检查型异常(checked exception)。无论何时使用这个方法,都应该提供一个异常处理器。

第三种获得Class对象的方法是,如果T是任意的Java类型,T.class将代表匹配的Class对象。例如:

Class cl1 = Random.class; // import java.util.*
Class cl2 = int.class;
Class cl3 = Double[].class;

虚拟机为每个类型管理一个唯一的Class对象,因此,可以利用==运算符实现两个Class对象的比较。例如:

if (e.getClass() == Employee.getClass()) ...

如果有一个Class对象,可以用它构造类的实例。调用getConstructor方法将得到一个Constructor类型的对象,然后使用newInstance方法来构造一个实例。例如:

String className = "java.util.Random";
Class cl = Class.forName(className);
Object obj = cl.getConstructor().newInstance();

这两个方法的签名为:

/* java.lang.Class */
Constructor getConstructor(Class... parameterTypes)
	// 生成一个对象,描述有指定参数类型的构造器。如果这个类没有参数匹配的构造器,会抛出异常

/* java.lang.reflect.Constructor */
Object newInstance(Object... params)
	// 将 params 传递到构造器,来构造这个构造器声明类的一个新实例

2 声明异常入门

上面提到forName方法可能抛出异常,调用这个方法时要提供异常处理器。下面简要介绍一些异常处理的内容。

当运行时发生错误时,程序就会抛出一个异常,可以提供一个处理器捕获这个异常并进行处理。如果没有提供处理器,程序就会终止,并在控制台上打印出一个消息,给出异常的类型。

异常有两种类型:非检查型异常和检查型异常。对于检查型异常,这类异常难以避免,编译器将会检查这类异常,在编译阶段提示程序员解决问题。非检查型异常不检查,在编译阶段不报错,一般可以避免。例如,数组越界和访问null引用属于非检查型异常。

如果一个方法包含可能抛出检查型异常的语句,则在方法名上添加一个throws子句,调用这个方法的任何方法也都需要一个throws声明。例如:

public static void doSomethingWithClass(String name)
		throws ReflectiveOperationException
{
   
	Class cl = Class.forName(name); // 可能抛出异常
	// do something with cl
}

如果调用了一个可能抛出检查型异常的方法而没有提供相应的异常处理器,编译器就会报错。

3 利用反射分析类的能力

java.lang.reflect包中有三个类FieldMethodConstructor,分别用于描述类的字段、方法和构造器。这三个类都有getName方法,用来返回字段、方法或构造器的名称:

String getName()

Field类有一个getType方法,用来返回描述字段类型的一个Class对象:

Class getType()

MethodConstructor类中的getParameterTypes方法返回参数类型:

Class[] getParameterTypes()

Method类中的getReturnType方法得到返回类型:

Class getReturnType()

这三个类都有一个getModifier方法,它返回一个整数,描述这个构造器、方法或字段的修饰符。可以使用Modifier类中的方法来分析这个整数值。

/* java.lang.reflect.Field/Method/Constructor */
int getModifier()

/* java.lang.reflect.Modifier */
static String toString(int modifiers)
	// 返回一个字符串,包含 modifiers 中对应的修饰符
static boolean isAbstract(int modifiers)
static boolean isFinal(int modifiers)
static boolean isInterface(int modifiers)
static boolean isNative(int modifiers)
static boolean isPrivate(int modifiers)
static boolean isProtected(int modifiers)
static boolean isPublic(int modifiers)
static boolean isStatic(int modifiers)
static boolean isStrict(int modifiers)
static boolean isSynchronized(int modifiers)
static boolean isVolatile(int modifiers)
	// 判断整数是否包含对应的修饰符

Class类中提供了一些返回FieldMethodConstructor对象的方法:

/* java.lang.Class */
Field getField(String name) // 得到指定名称的公共字段
Field[] getFields() // 返回这个类及其超类的公共字段
Field getDeclaredField(String name) // 得到指定名称的字段
Field[] getDeclaredFields() // 返回这个类的所有字段,不包括超类的字段
Method getMethod(String name, Class... parameterTypes) // 返回这个类中指定名称和参数类型的公共方法
Method[] getMethods() // 返回所有的公共方法,包括从超类继承来的公共方法
Method getDeclaredMethod(String name, Class... parameterTypes) // 返回这个类中指定名称和参数类型的方法
Method[] getDeclared
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值