RTTI
RTTI
(Run-Time Type Identification)是一种在运行时确定对象类型的机制。它是一种编程语言特性,主要用于在运行时动态识别和处理对象的实际类型。
通过 RTTI
,可以在运行时根据对象的实际类型执行相应的操作。这在处理多态对象和基于继承的代码逻辑时非常有用。
Java中的RTTI
在Java中,RTTI
主要通过以下两种方式实现:
-
instanceof
运算符:假定我们在编译时已经知道了所有的类型,可以使用instanceof
运算符来检查对象是否是特定类的实例或其子类的实例。它返回一个布尔值来指示对象是否可以转换为指定的类型。例如:
if (obj instanceof MyClass) {
// 对象是MyClass类型或其子类的实例
}
-
getClass()
方法:利用反射机制,在运行时发现和使用类的信息每个Java对象都有
getClass()
方法,它返回一个表示对象所属类的 Class 对象。可以使用getClass()
方法来获取对象的实际运行时类型。例如:
Class clazz = obj.getClass(); // 获取对象的实际类型
反射机制
反射机制是指在运行时动态地获取类的信息并操作类和对象的方法和属性。它是一种 Java 语言的特性,可以让程序在运行时获取类的信息,包括类型、属性、方法等,并且可以在运行时动态地创建对象、调用对象的方法、修改属性等。
Java反射机制的实现是通过 Java.lang.Class
类来实现的,Class类提供了许多方法来获取类的信息。通过 Class 类可以获取类的名称、继承关系、方法、属性等,还可以创建对象、调用方法等。
优点
Java 反射机制的优点是可以动态地获取和使用类的信息,这使得 Java 程序的灵活性更高,开发人员可以根据需要在运行时动态地调整程序,让程序更加灵活、可扩展。
缺点
-
破坏封装:由于反射允许访问私有字段和私有方法,所以可能会破坏封装而导致安全问题。
-
性能开销:由于反射涉及到动态解析,因此无法执行 Java 虚拟机优化,再加上反射的写法的确要复杂得多,所以性能要比“正射(直接使用类)”差很多,在一些性能敏感的程序中应该避免使用反射。
Java 反射机制的性能相对较低,使用不当还可能会导致程序运行失败或者出现安全漏洞,需要根据具体情况仔细使用。
应用场景
-
开发通用框架:例如 Spring,为了保持通用性,通过配置文件来加载不同的对象,调用不同的方法。
-
动态代理:在 面向切面编程(AOP)中,需要拦截特定的方法,就会选择动态代理的方式,而动态代理的底层技术就是反射。
-
注解:注解本身只是起到一个标记符的作用,它需要利用反射机制,根据标记符去执行特定的行为。
-
RPC框架:RPC(远程过程调用)框架通过反射机制动态地生成类和方法调用,实现远程服务的调用。
-
单元测试:在单元测试中,可以使用反射机制来调用私有方法或访问私有成员变量,从而进行更全面的测试。
反射机制的使用
Class 类
在Java中,Class类是反射机制的核心类之一,与class关键字不同。每个类都有一个与之关联的Class对象,该对象包含了有关类的元数据信息(如类的名称、字段、方法、构造函数等)。
Class类,位于 JDK 的 java.lang
包中。Class类的实例表示 java 应用运行时的 类 class ans enum
或 接口 interface and annotation
java.lang.class
是所有反射API的入口
-
手动编写的类被编译后(JVM 加载类时)会产生一个 Class对象,其表示的是创建的类的元数据,这个 Class对象保存在
同名.class
的文件中(字节码文件) -
每个通过关键字
class
标识的类,在 JVM 中有且只有一个与之对应的Class对象来描述其类型信息,无论创建多少个实例对象,其依据的都是用一个 Class对象。 -
Class类 只存私有构造函数,因此对应Class对象只能由JVM创建和加载
-
Class类 的对象作用是运行时提供或获得某个对象的类型信息,这点对于反射技术很重要
源代码
数组同样也被映射为 class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
基本类型 boolean
,byte
,char
,short
,int
,long
,float
,double
和关键字 void
同样表现为 class 对象。
每个 java类 运行时都在 JVM 里表现为一个 class对象,可通过类名.class
、