使用变量调用Java对象常量

时间:2019-06-15 04:46:28

标签: java reflection invoke

我对Java还是很陌生,所以我很难解释我要做什么。

我有一个抽象类,它调用了几个这样的对象常量:

public abstract class Enchantment implements Keyed {
    /**
     * Provides protection against environmental damage
     */
    public static final Enchantment PROTECTION_ENVIRONMENTAL = new EnchantmentWrapper("protection");

在另一个文件中,我可以使用
Enchantment value = Enchantment.PROTECTION_ENVIRONMENTAL;

但是,我正尝试为此使用字符串变量。像这样:

String str = "PROTECTION_ENVIRONMENTAL";
Enchantment value = Enchantment.str;

显然那是行不通的。因此,我进行了大量研究,并了解到需要对此进行反思。使用此源代码的文档,我认为我正在寻找字段数据。所以我都尝试了:

Field fld = Enchantment.class.getField("PROTECTION_ENVIRONMENTAL");
Field fld = Enchantment.class.getDeclaredField("PROTECTION_ENVIRONMENTAL");

但是这些返回了我NoSuchFieldException。在进行此操作时,我同样尝试了getMethod()getDeclaredMethod(),但都没有碰运气。

我现在说的是这些可能是“对象常量”?我不确定如何称呼他们。但是我绝对不知道如何使它现在开始工作,在尝试了所有方法之后,我认为是时候在这里寻求帮助了。

3 个答案:

答案 0 :(得分:3)

如果您知道枚举将是常量值,则可能需要调查一下;

public enum Enchantment {
    PROTECTION_ENVIRONMENTAL {
        public void cast() {
            // do enum-specific stuff here
        }
    },
    ANOTHER_ENCHANTMENT {
        public void cast() {
            // do enum-specific stuff here
        }
    },
    A_THIRD_ENCHANTMENT{
        public void cast() {
            // do enum-specific stuff here
        }
    };

    public abstract void cast();
}

枚举可以像类一样对待,并具有方法和属性。您还可以在字符串Enchantment.valueOf("PROTECTION_ENVIRONMENTAL")之间来回转换,但这通常是在从配置文件中读取时-在代码中直接引用该值。

答案 1 :(得分:3)

上面有一个评论:您绝对在这里不要使用反射。

使用反射只有两个有效的理由:

  • 您正在创建一个必须处理不了解的类的框架
  • 由于其他原因,您不得不处理编译时不知道的类

但是您的代码完全了解该Enchantment类,其功能等等。因此,反射是错误的方法。您自己想像得出:该死的很难做对,而该死的正确做错了一些微妙的方式。当您弄错了它时,它总是在运行时崩溃。反射代码 compiling 毫无意义。它总是在等待您运行它以吐在您的脸上。

因此通过不回答来回答您的问题:使用地图。喜欢:

Map<String, Enchantment> enchantmentsByConstantName = new HashMap<>();
enchantmentsByConstantName.put("PROTECTION_ENVIRONMENTAL", PROTECTION_ENVIRONMENTAL);

或者,如其他答案所述,这些常量也可以放入一个枚举中,但方式明显不同:

enum EnchantmentHolder {
  PROTECTION_ENVIRONMENTAL(new EnchantmentWrapper("protection")),
  ANOTHER_ENCHANTMENT(...)
  A_THIRD_ENCHANTMENT(...)
  ...;

  private Enchantment enchantment;

  private EnchantmentHolder(Enchantment enchantment) {
    this.entchantment = entchantment;
  }

  public Enchantment getEntchantment() { return entchantment; }

答案 2 :(得分:2)

拥有Field后,您需要使用实例(在这种情况下为class)调用Field.get(Object)。像

Class<?> cls = Enchantment.class;
try {
    Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
    System.out.println(f.get(cls));
} catch (Exception e) {
    e.printStackTrace();
}

由于您需要Enchantment,因此 可以 ,然后测试所获得的实例是否可分配给Enchantment。像

Class<? extends Enchantment> cls = Enchantment.class;
try {
    Field f = cls.getField("PROTECTION_ENVIRONMENTAL");
    Object obj = f.get(cls);
    if (cls.isAssignableFrom(obj.getClass())) {
        Enchantment e = cls.cast(obj);
        System.out.println(e);
    }
} catch (Exception e) {
    e.printStackTrace();
}

但是enum方法更好