Java 反射获取类的属性
在 Java 中,反射机制允许程序在运行时检查和操作类、方法、字段等,以下是使用反射获取类属性(字段)的几种方法:
基本方法获取所有字段
import java.lang.reflect.Field;
public class ReflectionExample {
public static void main(String[] args) {
try {
// 获取Class对象
Class<?> clazz = MyClass.class;
// 获取所有声明的字段(包括私有字段)
Field[] fields = clazz.getDeclaredFields();
// 遍历字段
for (Field field : fields) {
System.out.println("字段名: " + field.getName());
System.out.println("字段类型: " + field.getType());
System.out.println("修饰符: " + java.lang.reflect.Modifier.toString(field.getModifiers()));
System.out.println("----------------------");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyClass {
private int id;
public String name;
protected double price;
boolean available;
}
获取特定字段
// 获取特定名称的字段
try {
Field idField = clazz.getDeclaredField("id");
System.out.println("找到字段: " + idField.getName());
} catch (NoSuchFieldException e) {
System.out.println("未找到该字段");
}
获取父类字段
// 获取所有字段(包括继承的)
Field[] allFields = clazz.getFields(); // 只能获取public字段
// 或者递归获取父类字段
Field[] allFields = getAllFields(clazz);
private static Field[] getAllFields(Class<?> clazz) {
List<Field> fields = new ArrayList<>();
while (clazz != null) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
return fields.toArray(new Field[0]);
}
获取字段值
MyClass obj = new MyClass();
obj.name = "测试";
try {
Field nameField = clazz.getDeclaredField("name");
// 设置可访问(即使字段是私有的)
nameField.setAccessible(true);
// 获取字段值
Object value = nameField.get(obj);
System.out.println("字段值: " + value);
} catch (Exception e) {
e.printStackTrace();
}
设置字段值
try {
Field priceField = clazz.getDeclaredField("price");
priceField.setAccessible(true);
// 设置字段值
priceField.set(obj, 99.99);
System.out.println("设置后的价格: " + obj.getPrice());
} catch (Exception e) {
e.printStackTrace();
}
注意事项
- 访问控制:默认情况下,反射不能访问私有字段,需要调用
setAccessible(true)来解除访问限制 - 性能:反射操作比直接访问慢,应避免在性能敏感的代码中频繁使用
- 安全性:反射可以绕过访问控制,可能破坏封装性
- 类型安全:反射操作需要处理类型检查和转换
实用工具方法
public class ReflectionUtils {
/**
* 获取对象的所有字段名和值
*/
public static Map<String, Object> getFieldValues(Object obj) {
Map<String, Object> values = new HashMap<>();
if (obj == null) return values;
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object value = field.get(obj);
values.put(field.getName(), value);
} catch (IllegalAccessException e) {
values.put(field.getName(), "[无法访问]");
}
}
return values;
}
}
使用示例:
MyClass obj = new MyClass(); obj.name = "测试"; obj.price = 99.99; Map<String, Object> values = ReflectionUtils.getFieldValues(obj); System.out.println(values);
反射是Java强大的特性,但应谨慎使用,遵循"在必要时才使用"的原则。
