使用变量调用 Java 对象常量
Invoke Java object constant using a variable
我是 Java 的新手,所以很难解释我想做什么。
我有一个抽象 class 调用几个对象常量,如下所示:
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()
同样没有运气。
我现在说这些可能是 "object constants"?我不确定如何称呼他们。但我现在肯定不知道如何让它工作,在我自己尝试了一切之后,我想是时候在这里寻求帮助了。
如果您知道枚举将是常量值,您可能想研究一下枚举;
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")
但通常情况下,如果您正在从配置文件中读取数据 - 在代码中您会直接引用该值。
获得 Field
后,您需要使用实例调用 Field.get(Object)
(在本例中为 class
)。像,
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
方法更好。
那条评论是正确的:你绝对不要在这里使用反射。
使用反射只有两个正当理由:
- 您正在创建一个必须处理class它不知道的
的框架
- 您出于其他原因需要处理 class您在编译时不知道的问题
但是您的代码完全了解该附魔 class、它的功能等等。因此 reflection 是错误的做法。你自己想通了:做对很难,而在某些微妙的方面做错了也是对的。当你弄错时,它总是在 运行 时间爆炸。反射代码编译没有任何意义。它总是等着你 运行 吐在你的脸上。
因此,通过不回答来回答您的问题:使用地图。喜欢:
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; }
我是 Java 的新手,所以很难解释我想做什么。
我有一个抽象 class 调用几个对象常量,如下所示:
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()
同样没有运气。
我现在说这些可能是 "object constants"?我不确定如何称呼他们。但我现在肯定不知道如何让它工作,在我自己尝试了一切之后,我想是时候在这里寻求帮助了。
如果您知道枚举将是常量值,您可能想研究一下枚举;
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")
但通常情况下,如果您正在从配置文件中读取数据 - 在代码中您会直接引用该值。
获得 Field
后,您需要使用实例调用 Field.get(Object)
(在本例中为 class
)。像,
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
方法更好。
那条评论是正确的:你绝对不要在这里使用反射。
使用反射只有两个正当理由:
- 您正在创建一个必须处理class它不知道的 的框架
- 您出于其他原因需要处理 class您在编译时不知道的问题
但是您的代码完全了解该附魔 class、它的功能等等。因此 reflection 是错误的做法。你自己想通了:做对很难,而在某些微妙的方面做错了也是对的。当你弄错时,它总是在 运行 时间爆炸。反射代码编译没有任何意义。它总是等着你 运行 吐在你的脸上。
因此,通过不回答来回答您的问题:使用地图。喜欢:
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; }