方法一:獲取所有聲明的字段(包括 private)

使用 Class.getDeclaredFields() 可以獲取類中所有顯式聲明的字段(不包括繼承自父類的字段)。

import java.lang.reflect.Field;

public class FieldNameExample {
    private String name;
    public int age;
    protected boolean active;
    static double version;

    public static void main(String[] args) {
        Class<?> clazz = FieldNameExample.class;
        Field[] fields = clazz.getDeclaredFields();

        System.out.println("類 " + clazz.getSimpleName() + " 的字段名:");
        for (Field field : fields) {
            System.out.println("- " + field.getName());
        }
    }
}

輸出:

類 FieldNameExample 的字段名:
- name
- age
- active
- version

🔹 getDeclaredFields() 包含 privateprotectedpublicpackage-private 字段,也包含 static 字段。
🔹 不包含父類字段

方法二:獲取所有公共字段(包括繼承的)

使用 Class.getFields() 只能獲取 public 字段,且包含從父類或接口繼承的 public 字段

Field[] publicFields = clazz.getFields();
for (Field f : publicFields) {
    System.out.println(f.getName());
}

⚠️ 如果你的字段是 privateprotectedgetFields() 是拿不到的!

方法三:遞歸獲取類及其所有父類的字段

如果你需要包含父類(如 Object 除外)的所有字段,可以遞歸遍歷:

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public static List<Field> getAllFields(Class<?> clazz) {
    List<Field> fields = new ArrayList<>();
    while (clazz != null && clazz != Object.class) {
        fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        clazz = clazz.getSuperclass();
    }
    return fields;
}

使用示例:

List<Field> allFields = getAllFields(MySubClass.class);
allFields.forEach(f -> System.out.println(f.getName()));

方法四:只獲取字段名(字符串列表)

如果你只需要字段名(String),可以用 Stream 簡化:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public static List<String> getFieldNames(Class<?> clazz) {
    return Arrays.stream(clazz.getDeclaredFields())
                 .map(Field::getName)
                 .collect(Collectors.toList());
}

// 使用
List<String> names = getFieldNames(User.class);
System.out.println(names); // [id, username, email]