在 Java 中是否可以从实际字段中获取字符串中的字段名称?喜欢:
public class mod {
@ItemID
public static ItemLinkTool linkTool;
public void xxx{
String fieldsName = *getFieldsName(linkTool)*;
}
}
PS:我 不是 在寻找字段的类/类名或从字符串中的名称获取字段。
编辑:当我查看它时,我可能不需要一种方法来获取字段名称,Field 实例(来自字段的“代码名称”)就足够了。 [例如 Field myField = getField(linkTool)
]
Java 本身可能没有我想要的东西。我会看一下 ASM 库,但最后我可能会使用字符串作为字段的标识符:/
EDIT2:我的英语不是很好(但即使用我的母语我也很难解释这一点),所以我再添加一个例子。希望现在会更清楚:
public class mod2 {
@ItemID
public static ItemLinkTool linkTool;
@ItemID
public static ItemLinkTool linkTool2;
@ItemID
public static ItemPipeWrench pipeWrench;
public void constructItems() {
// most trivial way
linkTool = new ItemLinkTool(getId("linkTool"));
linkTool2 = new ItemLinkTool(getId("linkTool2"));
pipeWrench = new ItemPipeWrench(getId("pipeWrench"));
// or when constructItem would directly write into field just
constructItem("linkTool");
constructItem("linkTool2");
constructItem("pipeWrench");
// but I'd like to be able to have it like this
constructItemIdeal(linkTool);
constructItemIdeal(linkTool2);
constructItemIdeal(pipeWrench);
}
// not tested, just example of how I see it
private void constructItem(String name){
Field f = getClass().getField(name);
int id = getId(name);
// this could be rewritten if constructors take same parameters
// to create a new instance using reflection
if (f.getDeclaringClass() == ItemLinkTool){
f.set(null, new ItemLinkTool(id));
}else{
f.set(null, new ItemPipeWrench(id));
}
}
}
问题是:如何查看 constructItemIdeal 方法? (从答案和谷歌搜索我认为这在 Java 中是不可能的,但谁知道..)
原文由 monnef 发布,翻译遵循 CC BY-SA 4.0 许可协议
不幸的是,没有办法做你想做的事。 为什么?
在我们仍在努力证明 Java 并不慢的时代,存储对象在何处或如何构造的元数据会产生很大的开销,而且由于它的使用范围非常小,因此不存在。不仅如此:还有很多技术原因。
原因之一是 JVM 的实现方式。可在 此处 找到 Java
class
文件格式的规范。这是一个满口,但它是非常有用的。正如我之前所说,可以从任何地方构造一个对象,甚至是 对象没有名称 的情况。只有定义为类成员的对象才有名称(出于访问的明显原因):在方法中构造的对象没有。 JVM 有一个局部变量表,最多有 65535 个条目。这些被加载到堆栈并通过 *load 和 *store 操作码存储到表中。
换句话说,像这样的类
被编译成
在那里,您可以从
javap -v Test
中看到一个清晰的示例,虽然名称class_member
被保留,但my_local_field
已被抽象到索引表中的局部变量(1 0 保留给this
)。这本身会给调试器等带来痛苦,因此设计了一组属性(想想类文件的元数据)。其中包括 LocalVariableTable 、 LineNumberTable 和 LocalVariableTypeTable 。这些属性对于堆栈跟踪 (LineNumberTable) 和调试器(LocalVariableTable 和 LocalVariableTypeTable)很有用。但是,这些是 完全可选的,可以包含在文件中,并且不能保证它们是:
其他人也是如此。
此外,大多数编译器默认情况下只生成 LineNumberTable 以外的任何东西,因此即使可能,你也会倒霉。
基本上,对于开发人员来说,拥有一个
getFieldName(object)
(对于局部变量来说首先是不可能的)并且只有在这些属性存在时它才起作用,这将是非常令人沮丧的。因此,在可预见的未来,您将无法使用
getField
和字符串。无耻的插件: IntelliJ 似乎可以很好地处理反射重构:我也编写过 Minecraft 模组,我知道这种感觉,可以说 IntelliJ 显着减少了重构工作。但对于大多数现代 IDE 来说,情况可能也是如此:我敢肯定大玩家 Eclipse、Netbeans 等。 有实施良好的重构系统。