获取和设置字段值

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

给定一个类的实例,可以使用反射来设置该类中的字段值。这通常仅在特殊情况下才能以通常方式设置值。由于此类访问通常违反了该类的设计意图,因此应谨慎使用。

Book 类说明了如何设置 long,array 和 enum 字段类型的值。获取和设置其他原始类型的方法在 Field 中描述。

  1. import java.lang.reflect.Field;
  2. import java.util.Arrays;
  3. import static java.lang.System.out;
  4. enum Tweedle { DEE, DUM }
  5. public class Book {
  6. public long chapters = 0;
  7. public String[] characters = { "Alice", "White Rabbit" };
  8. public Tweedle twin = Tweedle.DEE;
  9. public static void main(String... args) {
  10. Book book = new Book();
  11. String fmt = "%6S: %-12s = %s%n";
  12. try {
  13. Class<?> c = book.getClass();
  14. Field chap = c.getDeclaredField("chapters");
  15. out.format(fmt, "before", "chapters", book.chapters);
  16. chap.setLong(book, 12);
  17. out.format(fmt, "after", "chapters", chap.getLong(book));
  18. Field chars = c.getDeclaredField("characters");
  19. out.format(fmt, "before", "characters",
  20. Arrays.asList(book.characters));
  21. String[] newChars = { "Queen", "King" };
  22. chars.set(book, newChars);
  23. out.format(fmt, "after", "characters",
  24. Arrays.asList(book.characters));
  25. Field t = c.getDeclaredField("twin");
  26. out.format(fmt, "before", "twin", book.twin);
  27. t.set(book, Tweedle.DUM);
  28. out.format(fmt, "after", "twin", t.get(book));
  29. // production code should handle these exceptions more gracefully
  30. } catch (NoSuchFieldException x) {
  31. x.printStackTrace();
  32. } catch (IllegalAccessException x) {
  33. x.printStackTrace();
  34. }
  35. }
  36. }

这是相应的输出:

  1. $ java Book
  2. BEFORE: chapters = 0
  3. AFTER: chapters = 12
  4. BEFORE: characters = [Alice, White Rabbit]
  5. AFTER: characters = [Queen, King]
  6. BEFORE: twin = DEE
  7. AFTER: twin = DUM

Note: Setting a field’s value via reflection has a certain amount of performance overhead because various operations must occur such as validating access permissions. From the runtime’s point of view, the effects are the same, and the operation is as atomic as if the value was changed in the class code directly.

Use of reflection can cause some runtime optimizations to be lost. For example, the following code is highly likely be optimized by a Java virtual machine:

  1. int x = 1;
  2. x = 2;
  3. x = 3;

使用Field.set*()的等效代码可能不会。