Java 反射機制允許運行時動態獲取類的結構信息。獲取屬性值的標準模式是:通過反射獲取字段名 → 按 JavaBean 規範拼接 getter 方法名(如 userName → getUserName()) → 通過反射調用 getter 方法獲取值。這種方式比直接訪問字段更安全,尊重了封裝性。
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
/**
* 參數基類:提供通過反射獲取所有屬性名與值的功能
* 子類繼承此類即可獲得 getClassInfo() 能力
*/
public class ParameterBase {
/**
* 獲取當前對象所有屬性及其值的 Map
* @return 屬性名-值映射
*/
public Map<String, String> getClassInfo() {
Map<String, String> fieldsAndValues = new HashMap<>();
// 獲取聲明的所有字段(包含 private)
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
String fieldName = field.getName();
// 通過反射調用 getter 獲取值
String value = getFieldValue(this, fieldName);
fieldsAndValues.put(fieldName, value);
}
return fieldsAndValues;
}
/**
* 獲取指定屬性的值
*/
private String getFieldValue(Object owner, String fieldName) {
return invokeMethod(owner, fieldName, null).toString();
}
/**
* 反射調用 getter 方法
* @param owner 目標對象
* @param fieldName 屬性名
* @param args 方法參數(getter 無參)
* @return 方法返回值
*/
private Object invokeMethod(Object owner, String fieldName, Object[] args) {
Class<? extends Object> ownerClass = owner.getClass();
// 拼接 getter 方法名:首字母大寫 + "get" 前綴
String methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
Method method = null;
try {
method = ownerClass.getMethod(methodName);
} catch (NoSuchMethodException e) {
// 沒有對應的 getter,返回空字符串
return "";
} catch (SecurityException e) {
// 安全限制,返回空字符串
return "";
}
try {
return method.invoke(owner);
} catch (Exception e) {
// 調用異常,返回空字符串
return "";
}
}
}
public class User extends ParameterBase {
private String userName;
private String passWorld;
// 標準 getter/setter
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
public String getPassWorld() { return passWorld; }
public void setPassWorld(String passWorld) { this.passWorld = passWorld; }
public static void main(String[] args) {
User u = new User();
u.setUserName("aaaaa");
u.setPassWorld("123");
// 獲取所有屬性值
System.out.println(u.getClassInfo());
// 輸出:{passWorld=123, userName=aaaaa}
}
}
getDeclaredFields():獲取類聲明的所有字段,包含 private、protected、default、public,**不包含繼承的字段**getFields():只獲取 public 字段,**包含繼承的字段**遵循 JavaBean 規範:
isXxx() 或 getXxx()getXxx()userName → getUserName()代碼捕獲了三類異常並統一返回空字符串:
NoSuchMethodException:沒有對應的 getter 方法SecurityException:安全管理器禁止訪問Exception:調用過程中的其他異常(如 IllegalAccessException、InvocationTargetException)private String getGetterName(String fieldName, Class<?> fieldType) {
if (fieldType == boolean.class || fieldType == Boolean.class) {
return "is" + capitalize(fieldName);
}
return "get" + capitalize(fieldName);
}
private String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
public Map<String, String> getClassInfoIncludingInherited() {
Map<String, String> result = new HashMap<>();
Class<?> clazz = this.getClass();
while (clazz != null && clazz != Object.class) {
for (Field field : clazz.getDeclaredFields()) {
if (!result.containsKey(field.getName())) {
result.put(field.getName(), getFieldValue(this, field.getName()));
}
}
clazz = clazz.getSuperclass();
}
return result;
}
public Map<String, Object> getClassInfoAsObject() {
Map<String, Object> result = new HashMap<>();
for (Field field : this.getClass().getDeclaredFields()) {
result.put(field.getName(), invokeMethod(this, field.getName(), null));
}
return result;
}
反射調用比直接調用慢,若在高頻熱點路徑使用,建議:
Method 對象(使用 ConcurrentHashMap)MethodHandle(Java 7+)