检索和解析字段修饰符

原文: https://docs.oracle.com/javase/tutorial/reflect/member/fieldModifiers.html

有几个修饰符可能是字段声明的一部分:

  • 访问修饰符:publicprotectedprivate
  • 控制运行时行为的字段特定修饰符:transientvolatile
  • 修饰符限制为一个实例:static
  • 修饰符禁止修改值:final
  • 注释

方法 Field.getModifiers() 可用于返回表示该字段的声明修饰符集的整数。表示该整数中的修饰符的位在 java.lang.reflect.Modifier 中定义。

FieldModifierSpy 示例说明了如何搜索具有给定修饰符的字段。它还通过分别调用 Field.isSynthetic()Field.isEnumCostant() 来确定所定位的字段是合成的(编译器生成的)还是枚举常量。

  1. import java.lang.reflect.Field;
  2. import java.lang.reflect.Modifier;
  3. import static java.lang.System.out;
  4. enum Spy { BLACK , WHITE }
  5. public class FieldModifierSpy {
  6. volatile int share;
  7. int instance;
  8. class Inner {}
  9. public static void main(String... args) {
  10. try {
  11. Class<?> c = Class.forName(args[0]);
  12. int searchMods = 0x0;
  13. for (int i = 1; i < args.length; i++) {
  14. searchMods |= modifierFromString(args[i]);
  15. }
  16. Field[] flds = c.getDeclaredFields();
  17. out.format("Fields in Class '%s' containing modifiers: %s%n",
  18. c.getName(),
  19. Modifier.toString(searchMods));
  20. boolean found = false;
  21. for (Field f : flds) {
  22. int foundMods = f.getModifiers();
  23. // Require all of the requested modifiers to be present
  24. if ((foundMods & searchMods) == searchMods) {
  25. out.format("%-8s [ synthetic=%-5b enum_constant=%-5b ]%n",
  26. f.getName(), f.isSynthetic(),
  27. f.isEnumConstant());
  28. found = true;
  29. }
  30. }
  31. if (!found) {
  32. out.format("No matching fields%n");
  33. }
  34. // production code should handle this exception more gracefully
  35. } catch (ClassNotFoundException x) {
  36. x.printStackTrace();
  37. }
  38. }
  39. private static int modifierFromString(String s) {
  40. int m = 0x0;
  41. if ("public".equals(s)) m |= Modifier.PUBLIC;
  42. else if ("protected".equals(s)) m |= Modifier.PROTECTED;
  43. else if ("private".equals(s)) m |= Modifier.PRIVATE;
  44. else if ("static".equals(s)) m |= Modifier.STATIC;
  45. else if ("final".equals(s)) m |= Modifier.FINAL;
  46. else if ("transient".equals(s)) m |= Modifier.TRANSIENT;
  47. else if ("volatile".equals(s)) m |= Modifier.VOLATILE;
  48. return m;
  49. }
  50. }

示例输出如下:

  1. $ java FieldModifierSpy FieldModifierSpy volatile
  2. Fields in Class 'FieldModifierSpy' containing modifiers: volatile
  3. share [ synthetic=false enum_constant=false ]
  4. $ java FieldModifierSpy Spy public
  5. Fields in Class 'Spy' containing modifiers: public
  6. BLACK [ synthetic=false enum_constant=true ]
  7. WHITE [ synthetic=false enum_constant=true ]
  8. $ java FieldModifierSpy FieldModifierSpy\$Inner final
  9. Fields in Class 'FieldModifierSpy$Inner' containing modifiers: final
  10. this$0 [ synthetic=true enum_constant=false ]
  11. $ java FieldModifierSpy Spy private static final
  12. Fields in Class 'Spy' containing modifiers: private static final
  13. $VALUES [ synthetic=true enum_constant=false ]

请注意,即使它们未在原始代码中声明,也会报告某些字段。这是因为编译器将生成运行时所需的一些合成字段。为了测试字段是否是合成的,该示例调用 Field.isSynthetic() 。合成字段集依赖于编译器;但是常用的字段包括this$0用于内部类(即非静态成员类的嵌套类)以引用最外层的封闭类和枚举用于实现隐式定义的静态方法values()$VALUES。未指定合成类成员的名称,并且在所有编译器实现或发行版中可能不相同。这些和其他合成字段将包括在 Class.getDeclaredFields() 返回的阵列中,但未被 Class.getField() 鉴定,因为合成成员通常不是public

因为 Field 实现了接口 java.lang.reflect.AnnotatedElement ,所以可以使用 java.lang.annotation.RetentionPolicy.RUNTIME 检索任何运行时注释。有关获取注释的示例,请参见检查类修饰符和类型部分。