核心概念
- 接口 (Interface): 定义了一组方法的契约,但不包含具体实现,它是一个类型。
- 实现类 (Implementation Class): 一个具体的类,使用
implements关键字声明它实现了某个或某些接口,并提供了接口中所有方法的具体实现。 - 反射 (Reflection): 在运行时,动态地获取一个类的信息(如字段、方法、构造函数等)并操作对象的能力,Java 的反射 API 主要在
java.lang.reflect包中。
反射操作接口和实现类的核心场景
我们通常通过反射来做以下几件事:

- 获取一个接口的
Class对象。 - 获取一个实现类的
Class对象。 - 检查一个类是否实现了某个接口。
- 动态创建实现类的实例。
- 动态调用实现类的方法。
详细步骤与代码示例
我们定义一个简单的接口和它的实现类作为演示。
定义接口和实现类
Animal.java (接口)
public interface Animal {
void makeSound();
String getName();
}
Dog.java (实现类)
public class Dog implements Animal {
private String name;
public Dog(String name) {
this.name = name;
}
@Override
public void makeSound() {
System.out.println(name + " says: Woof! Woof!");
}
@Override
public String getName() {
return this.name;
}
}
获取 Class 对象
获取 Class 对象有三种方式,推荐使用第三种(.class 语法),因为它最安全、简洁。

// 方式一: 通过类的全限定名 (字符串)
try {
Class<?> dogClass = Class.forName("com.example.reflect.Dog");
Class<?> animalClass = Class.forName("com.example.reflect.Animal");
System.out.println("通过 Class.forName 获取 Class 对象成功。");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 方式二: 通过对象的 getClass() 方法 (需要已有实例)
// Dog myDog = new Dog("Buddy");
// Class<?> dogClass = myDog.getClass();
// 方式三: 通过 .class 语法 (推荐)
Class<?> dogClass = Dog.class;
Class<?> animalClass = Animal.class;
System.out.println("Dog.class 的 Class 对象: " + dogClass.getName());
System.out.println("Animal.class 的 Class 对象: " + animalClass.getName());
检查类是否实现了接口
使用 Class 对象的 isAssignableFrom() 方法,这是一个非常关键的技巧。
classA.isAssignableFrom(classB)判断classB是否是classA的实例,或者classB是否是classA的子类或实现类。
// 检查 Dog 类是否实现了 Animal 接口
boolean isDogAnAnimal = Animal.class.isAssignableFrom(Dog.class);
System.out.println("Dog 是否是 Animal 的实现类? " + isDogAnAnimal); // 输出: true
// 检查 Animal 接口是否可以被 Dog 类赋值 (反过来就不行)
boolean isAnimalADog = Dog.class.isAssignableFrom(Animal.class);
System.out.println("Animal 是否是 Dog 的实现类? " + isAnimalADog); // 输出: false
// 检查 String 类是否实现了 Animal 接口
boolean isStringAnAnimal = Animal.class.isAssignableFrom(String.class);
System.out.println("String 是否是 Animal 的实现类? " + isStringAnAnimal); // 输出: false
动态创建实现类的实例
使用 Class 对象的 newInstance() 方法(已过时,不推荐)或 getDeclaredConstructor().newInstance() 方法(推荐)。
注意:如果类有无参构造函数,使用 getDeclaredConstructor().newInstance(),如果构造函数是私有的,需要先调用 setAccessible(true)。
try {
// --- 推荐方式 ---
// 1. 获取无参构造函数
Constructor<?> constructor = dogClass.getDeclaredConstructor();
// 2. 如果构造函数是私有的,需要设置为可访问
// constructor.setAccessible(true);
// 3. 创建实例
Object dogInstance = constructor.newInstance();
System.out.println("成功创建 Dog 实例: " + dogInstance);
// --- 不推荐的方式 (已过时) ---
// Object oldWayInstance = dogClass.newInstance();
// System.out.println("旧方式创建的实例: " + oldWayInstance);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
动态调用实现类的方法
这是反射最强大的功能之一,流程如下:
- 获取
Method对象:getMethod("方法名", 参数类型.class...)。 - 设置可访问性(如果方法是
private):method.setAccessible(true)。 - 调用方法:
method.invoke(对象实例, 参数值...)。
try {
// 1. 创建 Dog 实例
Constructor<?> constructor = dogClass.getDeclaredConstructor(String.class);
Object dogInstance = constructor.newInstance("Rex");
// 2. 获取 makeSound 方法的 Method 对象
// 注意:getMethod 是获取 public 方法
Method makeSoundMethod = dogClass.getMethod("makeSound");
// 3. 调用方法
// 第一个参数是调用该方法的对象实例,后续是方法参数
makeSoundMethod.invoke(dogInstance); // 输出: Rex says: Woof! Woof!
// 4. 获取 getName 方法的 Method 对象
Method getNameMethod = dogClass.getMethod("getName");
// 5. 调用方法并获取返回值
Object name = getNameMethod.invoke(dogInstance);
System.out.println("Dog's name is: " + name); // 输出: Dog's name is: Rex
// 如果调用的是私有方法
// Method privateMethod = dogClass.getDeclaredMethod("somePrivateMethod");
// privateMethod.setAccessible(true);
// privateMethod.invoke(dogInstance);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
完整的实践案例
假设我们有一个配置文件 config.properties,里面指定了要使用的实现类。
config.properties
animal.class.name=com.example.reflect.Dog
ReflectionDemo.java
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectionDemo {
public static void main(String[] args) {
// 1. 从配置文件中读取实现类的全限定名
Properties props = new Properties();
try (InputStream input = ReflectionDemo.class.getClassLoader().getResourceAsStream("config.properties")) {
props.load(input);
String className = props.getProperty("animal.class.name");
System.out.println("从配置文件读取到的类名: " + className);
// 2. 通过反射获取该类的 Class 对象
Class<?> clazz = Class.forName(className);
// 3. 检查它是否实现了 Animal 接口 (增加健壮性)
if (!Animal.class.isAssignableFrom(clazz)) {
System.err.println("错误: 配置的类 " + className + " 没有实现 Animal 接口。");
return;
}
// 4. 动态创建该类的实例
Constructor<?> constructor = clazz.getConstructor(String.class);
Object animalInstance = constructor.newInstance("Dynamic Dog");
// 5. 动态调用其方法
Method makeSoundMethod = clazz.getMethod("makeSound");
Method getNameMethod = clazz.getMethod("getName");
System.out.println("--- 开始调用动态创建的对象的方法 ---");
makeSoundMethod.invoke(animalInstance);
String name = (String) getNameMethod.invoke(animalInstance);
System.out.println("The animal's name is: " + name);
System.out.println("--- 调用结束 ---");
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果
从配置文件读取到的类名: com.example.reflect.Dog
--- 开始调用动态创建的对象的方法 ---
Dynamic Dog says: Woof! Woof!
The animal's name is: Dynamic Dog
--- 调用结束 ---
| 操作 | 关键 API/方法 | 说明 |
|---|---|---|
| 获取 Class 对象 | Class.forName("全限定名")MyClass.classmyObject.getClass() |
反射的起点,.class 语法最推荐。 |
| 检查接口实现 | interfaceClass.isAssignableFrom(classB) |
判断 classB 是否是 interfaceClass 的实现类或子类。 |
| 创建实例 | constructor.newInstance() |
获取构造函数后创建实例,比过时的 class.newInstance() 更灵活。 |
| 获取方法 | getMethod(name, paramTypes)getDeclaredMethod(name, paramTypes) |
getMethod 只获取 public 方法,getDeclaredMethod 获取所有声明的(包括 private)。 |
| 调用方法 | method.invoke(instance, args...) |
执行方法,instance 是方法所属的对象,args 是方法参数。 |
| 访问私有成员 | field.setAccessible(true)method.setAccessible(true) |
在获取到 Field 或 Method 后,设置为可访问,从而绕过访问控制。 |
通过反射,Java 程序可以在运行时动态地加载类、创建对象、调用方法,极大地提高了代码的灵活性和可扩展性,是许多高级框架(如 Spring、Hibernate、MyBatis)的基石。
