Java 反射总结
Java 反射是 Java 语言的一种特性,可以在运行时检查和调用类、方法、字段等详细信息,而不需要在编译时知道这些信息。
反射为 Java 提供了动态的能力,使程序可以在运行时动态地创建对象、调用方法、访问字段等。
基本概念
- Class对象:反射的核心类,通过它可以获得类的详细信息。
- Method对象:表示类中的方法,允许调用方法。
- Field对象:表示类中的成员变量,允许访问和修改变量。
- Constructor对象:表示类的构造函数,允许实例化对象。
获取 Class 对象的方式
获取 Class 对象的方式有:
- 使用类名 .class
- 使用 Class.forName("类的全限定名")
- 使用对象 .getClass()
- 使用 ClassLoader.loadClass() 方法
使用类名 .class
直接获取类对象的最简单方法,通常用于已知类的情况。
// 获取 String 类的 Class 对象
Class<String> clazz = String.class;
使用 Class.forName()
根据给定的类名(全限定名)在运行时加载类。它会抛出 ClassNotFoundException,因此需处理异常。
try {
// 通过类名获取 Class 对象
Class<?> clazz = Class.forName("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
使用对象 .getClass()
用于在运行时获取对象的类
// 通过对象获取 Class 对象
String str = "Hello, World!";
Class<? extends String> clazz = str.getClass();
使用 ClassLoader.loadClass() 方法
使用类加载器来加载类,通常只在特定情况下需要,如自定义类加载器。
try {
// 获取系统类加载器
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
// 通过类加载器加载 Class 对象
Class<?> clazz = classLoader.loadClass("java.lang.String");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
获取类的信息
能获取到的类的信息有:
- 获取类的名字
- 获取类的修饰符
- 获取类的注解
- 获取泛型类的泛型
- 获取类实现的接口
- 获取类的父类
获取类的名字
- 使用
Class.getName()方法获取类的全限定名,包括包名。
package com.demo;
public class Example {
public static void main(String[] args) {
Class<?> clazz = Example.class;
String className = clazz.getName();
System.out.println("Class name: " + className); //Class name: com.demo.Example
}
}
- 使用
Class.getSimpleName()方法返回类的简单名称,不包括包名。
package com.demo;
public class Example {
public static void main(String[] args) {
Class<?> clazz = Example.class;
String simpleName = clazz.getSimpleName();
System.out.println("Simple class name: " + simpleName); // Simple class name: Example
}
}
- 使用
Class.getCanonicalName()方法返回类的规范名称,如果类没有规范名称(如匿名类),则返回 null。
public class Example {
public static void main(String[] args) {
Class<?> clazz = Example.class;
String canonicalName = clazz.getCanonicalName();
System.out.println("Canonical class name: " + canonicalName); // Canonical class name: com.demo.Example
}
}
获取类的修饰符
使用 Class 类的 getModifiers()方法获取修饰符。
class SomeClass {
// 类定义
}
public class ModifierExample {
public static void main(String[] args) {
Class<?> clazz = SomeClass.class;
int modifiers = clazz.getModifiers();
System.out.println("Is public: " + Modifier.isPublic(modifiers));
System.out.println("Is abstract: " + Modifier.isAbstract(modifiers));
System.out.println("Is final: " + Modifier.isFinal(modifiers));
// 可以继续检查其他修饰符
}
}
- 输出结果:
Is public: false
Is abstract: false
Is final: false
获取类的注解
使用 Class 的 getAnnotation()方法
Class.getAnnotation(Class<T> annotationClass) 方法用于获取指定类型的注解。如果该注解不存在,则返回 null。
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
@MyAnnotation("ExampleClass")
class Example {
}
public class AnnotationExample1 {
public static void main(String[] args) {
Class<Example> obj = Example.class;
// 获取类上的注解
MyAnnotation annotation = obj.getAnnotation(MyAnnotation.class);
System.out.println("Value: " + annotation.value()); //Value: ExampleClass
}
}
使用 Class 的 getAnnotations()方法
Class.getAnnotations() 方法返回该元素上存在的所有注解,包含从超类继承的注解。
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value();
}
@MyAnnotation("ExampleClass")
class Example {
}
public class AnnotationExample2 {
public static void main(String[] args) {
Class<Example> obj = Example.class;
// 获取类上所有的注解
Annotation[] annotations = obj.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof MyAnnotation) {
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("Value: " + myAnnotation.value());//Value: ExampleClass
}
}
}
}
使用 Class 的 getDeclaredAnnotations()方法
Class.getDeclaredAnnotations() 方法返回直接存在于此元素上的所有注解,不包括继承的注解。
public class AnnotationExample3 {
public static void main(String[] args) {
Class<Example> obj = Example.class;
// 获取类上直接声明的所有注解
Annotation[] annotations = obj.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof MyAnnotation) {
MyAnnotation myAnnotation = (MyAnnotation) annotation;
System.out.println("Value: " + myAnnotation.value());
}
}
}
}
使用 AnnotatedElement 的 isAnnotationPresent()方法
Class.isAnnotationPresent(Class<? extends Annotation> annotationClass) 用于检查指定类型的注解是否存在。
public class AnnotationExample4 {
public static void main(String[] args) {
Class<Example> obj = Example.class;
// 检查注解是否存在
if (obj.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation = obj.getAnnotation(MyAnnotation.class);
System.out.println("Value: " + annotation.value());
} else {
System.out.println("MyAnnotation not present.");
}
}
}
获取泛型类的泛型
使用 Class 的 getGenericSuperclass()方法
如果一个类直接继承了一个带有泛型的父类,可以使用 getGenericSuperclass()获取父类的泛型类型。
class GenericClass<T> {
}
class StringGenericClass extends GenericClass<String> {
}
public class Main {
public static void main(String[] args) {
// 获取直接父类的泛型类型
Type genericSuperclass = StringGenericClass.class.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type type : actualTypeArguments) {
System.out.println(type.getTypeName()); // 输出:java.lang.String
}
}
}
}
使用 Class 的 getGenericInterfaces()方法
如果一个类实现了一个带有泛型的接口,可以使用 getGenericInterfaces()获取接口的泛型类型。
interface GenericInterface1<T> {
}
interface GenericInterface2<T> {}
class StringGenericClass implements GenericInterface1<String>, GenericInterface2<Integer> {
}
public class Main {
public static void main(String[] args) {
// 获取实现的接口的泛型类型
Type[] genericInterfaces = StringGenericClass.class.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
if (genericInterface instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type type : actualTypeArguments) {
System.out.println(type.getTypeName()); // 输出:java.lang.String 和 java.lang.Integer
}
}
}
}
}
获取类实现的接口
Class.getInterfaces() 方法返回表示类或接口直接实现的所有接口的数组。
public class InterfaceExample {
public static void main(String[] args) {
Class<?>[] interfaces = MyClass.class.getInterfaces();
for (Class<?> iface : interfaces) {
System.out.println(iface.getName());
}
}
}
interface MyInterface1 {}
interface MyInterface2 {}
class MyClass implements MyInterface1, MyInterface2 {}
获取类的父类
Class.getSuperclass() 方法可以用来获取一个类的直接父类。如果该类没有继承其他类(除了 Object 类),则返回 null。
class Parent {
}
class Child extends Parent {
}
public class Main {
public static void main(String[] args) {
Class<?> childClass = Child.class;
Class<?> parentClass = childClass.getSuperclass();
System.out.println("Parent class of Child: " + parentClass.getName()); //Parent class of Child: com.demo.Parent
}
}
操作类的字段
操作类的字段包括:
- 获取字段
- 访问字段的值
- 修改字段的值
获取类的字段信息
使用 Class 的 getField() 方法
该方法用于获取类的公共成员字段(public fields),包括从父类继承的公共字段。
abstract class AbstractClass {
public int abstractPublicField;
}
class MyClass extends AbstractClass{
public int publicField;
private String privateField;
}
public class Example {
public static void main(String[] args) {
try {
Class<?> clazz = MyClass.class;
Field field = clazz.getField("publicField");
System.out.println("Field Name: " + field.getName()); // Field Name: publicField
System.out.println("Field Type: " + field.getType()); // Field Type: int
System.out.println("Field Modifiers: " + field.getModifiers()); // Field Modifiers: 1
System.out.println("Field Declaring Class: " + field.getDeclaringClass()); // Field Declaring Class: class com.example.demo.MyClass
field = clazz.getField("abstractPublicField");
System.out.println("Field Name: " + field.getName()); // Field Name: abstractPublicField
System.out.println("Field Type: " + field.getType()); // Field Type: int
field = clazz.getField("privateField"); // java.lang.NoSuchFieldException: privateField
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
使用 Class.getFields() 方法
返回一个包含所有公共成员字段的数组,包括从父类继承的公共字段。
abstract class AbstractClass {
public int abstractPublicField;
}
class MyClass extends AbstractClass{
public int publicField;
private String privateField;
}
public class Example {
public static void main(String[] args) {
Class<?> clazz = MyClass.class;
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println("Public Field: " + field.getName());
// 输出结果
// Public Field: publicField
// Public Field: abstractPublicField
}
}
}
使用 Class.getDeclaredField() 方法
该方法用于获取类本身声明的字段(private, protected, package-private, public),但不包括从父类继承的字段。
class MyClass {
public int publicField;
private String privateField;
}
public class Example {
public static void main(String[] args) {
try {
Class<?> clazz = MyClass.class;
Field field = clazz.getDeclaredField("privateField");
System.out.println("Field Name: " + field.getName()); // Field Name: privateField
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
使用 Class.getDeclaredFields() 方法
返回一个包含类中声明的所有字段的数组,无论其访问修饰符是什么,但不包括从父类继承的字段。
class MyClass {
public int publicField;
private String privateField;
}
public class Example {
public static void main(String[] args) {
Class<?> clazz = MyClass.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("Declared Field: " + field.getName());
// 输出结果
// Declared Field: publicField
// Declared Field: privateField
}
}
}
访问字段的值
使用 Field.get() 方法
使用 Field 对象的 get(Object obj) 方法来获取指定对象上此 Field 表示的字段的值。
class Person {
private String name = "John";
}
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person();
// 获取 Person 类的 Class 对象
Class<?> clazz = person.getClass();
// 获取名为 "name" 的 Field 对象
Field field = clazz.getDeclaredField("name");
// 因为 name 是 private 的,所以需要设置为 true 以跳过访问检查
field.setAccessible(true);
// 获取 person 对象的 name 字段的值
String nameValue = (String) field.get(person);
System.out.println("Name: " + nameValue); // Name: John
}
}
通过 Field 的 getInt()、getBoolean() 等方法
如果知道字段的具体类型,可以使用对应的 getType() 方法来获取特定类型的字段值,例如 getInt()、getBoolean() 等。
class Person {
private String name = "John";
private int age = 30;
}
public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person();
// 获取 Person 类的 Class 对象
Class<?> clazz = person.getClass();
// 获取名为 "name" 的 Field 对象
Field field = clazz.getDeclaredField("age");
// 因为 name 是 private 的,所以需要设置为 true 以跳过访问检查
field.setAccessible(true);
// 获取 person 对象的 name 字段的值
int ageValue = field.getInt(person);
System.out.println("Age: " + ageValue); // Age: 30
}
}
使用 MethodHandle(Java 7 及以上版本)
从 Java 7 开始,可以使用 MethodHandles.Lookup 类来更高效地进行反射操作。
class Person {
public String name = "John";
private int age = 30;
}
public class Main {
public static void main(String[] args) throws Throwable {
Person person = new Person();
// 获取 VarHandle
VarHandle varHandle = MethodHandles.lookup().findVarHandle(Person.class, "name", String.class);
// 获取 person 对象的 name 字段的值
String nameValue = (String) varHandle.get(person);
System.out.println("Name: " + nameValue);
}
}
- 使用 MethodHandles 只能获取类的非私有变量,类似于 getFiled() 方法,可以获取自身与父类的非私有变量。
修改字段的值
import java.lang.reflect.Field;
public class ReflectionExample {
private String privateField = "Initial Value";
public static void main(String[] args) {
try {
ReflectionExample obj = new ReflectionExample();
Field field = ReflectionExample.class.getDeclaredField("privateField");
field.setAccessible(true);
field.set(obj, "Modified Value");
System.out.println(field.get(obj)); // 输出: Modified Value
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
操作类的构造函数
操作类的构造函数包括:
- 获取构造函数
- 创建根据构造函数实例
获取构造函数
获取所有公共构造函数
使用 Class.getConstructors()方法获取所有公共构造函数。
public class Example {
public Example() {}
private Example(String s) {}
public static void main(String[] args) {
try {
Class<?> cls = Example.class;
Constructor<?>[] constructors = cls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
获取所有构造函数(包括非公)
使用 Class.getDeclaredConstructors() 方法获取所有级别的构造函数。
public class Example {
private Example() {}
protected Example(int num) {}
Example(double value) {}
public Example(String s) {}
public static void main(String[] args) {
try {
Class<?> cls = Example.class;
Constructor<?>[] constructors = cls.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("Constructor: " + constructor);
// output:
// Constructor: public com.example.demo.Example(java.lang.String)
// Constructor: com.example.demo.Example(double)
// Constructor: protected com.example.demo.Example(int)
// Constructor: private com.example.demo.Example()
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
获取特定的构造函数
使用 Class.getConstructor(Class<?>... parameterTypes) 方法获取带有特定参数类型的公共构造函数。
public class Example {
public Example(String s) {}
public static void main(String[] args) {
try {
Class<?> cls = Example.class;
Constructor<?> constructor = cls.getConstructor(String.class);
System.out.println("Constructor: " + constructor);
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
}
获取特定的公共构造函数(包括非公)
使用 Class.getDeclaredConstructor(Class<?>... parameterTypes) 方法获取带有特定参数类型的构造函数,包括非公共构造函数。
import java.lang.reflect.Constructor;
public class Example {
private Example(String s) {}
public static void main(String[] args) {
try {
Class<?> cls = Example.class;
Constructor<?> constructor = cls.getDeclaredConstructor(String.class);
System.out.println("Constructor: " + constructor);
} catch (Exception e) {
e.printStackTrace();
}
}
}
根据构造函数创建实例
// Example.java
public class Example {
private String name = "John";
public Example() {}
private Example(String s) {
this.name = s;
}
public String getName() {
return name;
}
}
// Main.java
public class Main {
public static void main(String[] args) {
try {
Class<?> cls = Example.class;
Constructor<?> constructor = cls.getDeclaredConstructor();
Example e1 = (Example) constructor.newInstance();
System.out.println(e1.getName()); // John
constructor = cls.getDeclaredConstructor(String.class);
// 由于是私有构造函数,实例化时需要设置可访问性
constructor.setAccessible(true);
Example e2 = (Example) constructor.newInstance("Jane");
System.out.println(e2.getName()); // Jane
} catch (Exception e) {
e.printStackTrace();
}
}
}
操作类的方法
操作类的方法包括::
- 获取方法
- 调用方法
获取方法
获取所有公共方法(包括继承的方法)
使用 Class.getMethods() 方法可以获取某个类的所有公共方法,包括从父类继承的方法。
class AbstractClass {
public void abstractMethod() {}
}
class SampleClass extends AbstractClass {
public void sampleMethod() {}
private void privateMethod() {}
}
public class ReflectionExample {
public static void main(String[] args) {
Class<?> clazz = SampleClass.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println("Method Name: " + method.getName() + "; Declaring Class Name:" + method.getDeclaringClass().getSimpleName());
}
}
}
- 输出结果:
Method Name: sampleMethod; Class Name:SampleClass
Method Name: abstractMethod; Class Name:AbstractClass
Method Name: equals; Class Name:Object
Method Name: toString; Class Name:Object
Method Name: hashCode; Class Name:Object
Method Name: getClass; Class Name:Object
Method Name: notify; Class Name:Object
Method Name: notifyAll; Class Name:Object
Method Name: wait; Class Name:Object
Method Name: wait; Class Name:Object
Method Name: wait; Class Name:Object
获取所有声明的方法(不包括继承的方法)
使用 Class.getDeclaredMethods() 方法可以获取类中声明的所有方法,包括私有方法,但不包括继承的方法。
class AbstractClass {
public void abstractMethod() {}
}
class SampleClass extends AbstractClass {
public void sampleMethod() {}
private void privateMethod() {}
}
public class ReflectionExample {
public static void main(String[] args) {
Class<?> clazz = SampleClass.class;
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("Method Name: " + method.getName() + "; Declaring Class Name:" + method.getDeclaringClass().getSimpleName());
}
}
}
- 输出结果:
Method Name: sampleMethod; Declaring Class Name:SampleClass
Method Name: privateMethod; Declaring Class Name:SampleClass
获取特定的方法(只有非私有方法)
使用 Class.getMethod(String name, Class<?>... parameterTypes) 可以获取特定的公共方法。需要提供方法名和参数类型列表。
public class ReflectionExample {
public static void main(String[] args) {
try {
Class<?> clazz = SampleClass.class;
Method method = clazz.getMethod("sampleMethod");
System.out.println("Method Name: " + method.getName()); // Method Name: sampleMethod
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
class SampleClass {
public void sampleMethod() {}
}
获取特定的声明方法(包括私有方法)
使用 Class.getDeclaredMethod(String name, Class<?>... parameterTypes) 可以获取类中声明的特定方法,包括私有方法。
public class ReflectionExample {
public static void main(String[] args) {
try {
Class<?> clazz = SampleClass.class;
Method method = clazz.getDeclaredMethod("privateMethod");
System.out.println("Declared Method Name: " + method.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
class SampleClass {
private void privateMethod() {}
}
调用方法
调用无参数方法
public class ReflectionExample {
public void sayHello() {
System.out.println("Hello, World!");
}
public static void main(String[] args) {
try {
// 获取类的Class对象
Class<?> clazz = ReflectionExample.class;
// 创建类的实例
Object instance = clazz.getDeclaredConstructor().newInstance();
// 获取方法对象
Method method = clazz.getMethod("sayHello");
// 调用方法
method.invoke(instance);
} catch (Exception e) {
e.printStackTrace();
}
}
}
调用带参数的方法
public class ReflectionExample {
public void greet(String name) {
System.out.println("Hello, " + name);
}
public static void main(String[] args) {
try {
// 获取类的Class对象
Class<?> clazz = ReflectionExample.class;
// 创建类的实例
Object instance = clazz.getDeclaredConstructor().newInstance();
// 获取方法对象,指定参数类型
Method method = clazz.getMethod("greet", String.class);
// 调用方法,传递参数
method.invoke(instance, "Alice");
} catch (Exception e) {
e.printStackTrace();
}
}
}
调用私有方法
public class ReflectionExample {
private void secretMethod() {
System.out.println("This is a secret method!");
}
public static void main(String[] args) {
try {
// 获取类的Class对象
Class<?> clazz = ReflectionExample.class;
// 创建类的实例
Object instance = clazz.getDeclaredConstructor().newInstance();
// 获取私有方法对象
Method method = clazz.getDeclaredMethod("secretMethod");
// 设置方法为可访问
method.setAccessible(true);
// 调用方法
method.invoke(instance);
} catch (Exception e) {
e.printStackTrace();
}
}
}

浙公网安备 33010602011771号