获取字段的名称 [英] Get name of a field

查看:102
本文介绍了获取字段的名称的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java中是否可以从实际字段中获取字符串中的字段名称?喜欢:

Is it possible in Java to get a name of field in string from the actual field? like:

public class mod {
    @ItemID
    public static ItemLinkTool linkTool;

    public void xxx{
        String fieldsName = *getFieldsName(linkTool)*;
    }
}

PS:我查找字段的类/类名称或从String中的名称获取字段。

PS: I'm not looking for a field's class/class name or getting Field from name in String.

编辑:
当我查看它时,我可能不需要一个方法来获取字段的名称,Field实例(来自字段的代码名称)就足够了。 [例如。 字段myField = getField(linkTool)]

在Java本身可能没有我想要的东西。我将看看ASM库,但最后我可能最终使用字符串作为字段的标识符:/

There probably isn't anything like I want in Java itself. I'll take a look at the ASM library, but in the end I might end up using the string as an identifier for fields :/

EDIT2:
我的英语不是很好(但即使用我的母语,我也有解释这个问题),所以我再添加一个例子。希望现在更清楚了:

My english isn't great (but even in my native language I'd have problems explaining this), so I'm adding one more example. Hopefuly it will be more clear now:

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,但谁知道..)

The question is: how could look the constructItemIdeal method? (From answers and googling around I thing it's not possible in Java, but who knows..)

推荐答案

不幸的是,没有做你想做的事。 为什么?

Unfortunately, there is no way to do what you wish. Why?

在我们仍在努力证明Java不慢的时代,存储构造对象的位置或方式的元数据会产生很大的开销,并且因为它的使用范围非常小,所以它不存在。不仅如此:还有许多技术原因。

In an era where we are still trying to prove that Java is not slow, storing metadata of where or how an object was constructed would have a large overhead, and since it has a very minimal range of use, it does not exist. Not only that: there are a bunch of technical reasons as well.

一个原因是因为JVM的实现方式。可以找到Java 文件格式的规范这里。这是相当满口的,但它是非常丰富的信息。

One reason is because of how the JVM is implemented. The specification for the Java class file format can be found here. It's quite a mouthful, but it is very informative.

正如我之前所说,可以在任何地方构建对象,即使对象没有名称的情况也是如此。只有定义为类成员的对象才具有名称(出于显而易见的原因):在方法中构造的对象不具有名称。 JVM有一个局部变量表,最多包含65535个条目。它们被加载到堆栈并通过* load和* store操作码存储到表中。

As I said previously, an object can be constructed from anywhere, even situations where objects do not have names. Only objects defined as class members have names (for the obvious reason of access): objects constructed in methods do not. The JVM has a local variable table with a maximum of 65535 entries. These are loaded unto the stack and stored into the table via the *load and *store opcodes.

换句话说,类似

public class Test {
int class_member = 42;

   public Test() {
      int my_local_field = 42;
   }
}

汇编成

public class Test extends java.lang.Object
  SourceFile: "Test.java"
  minor version: 0
  major version: 50
  Constant pool:
  --snip--

{
int class_member;

public Test();
  Code:
   Stack=2, Locals=2, Args_size=1
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   bipush  42
   7:   putfield        #2; //Field class_member:I
   10:  bipush  42
   12:  istore_1
   13:  return
  LineNumberTable:
   --snip--    
}

在那里,你可以看到一个明确的例子来自 javap -v Test 当保留名称 class_member 时, my_local_field 已被抽象为局部变量表中的索引1 (0保留给这个)。

There, you can see a clear example from javap -v Test that while the name class_memberis preserved, the my_local_field has been abstracted to index 1 in the local variable table (0 is reserved for this).

这对于调试器来说本身就是一种痛苦,所以设计了一组属性(想想类文件的元数据)。其中包括 LocalVariableTable LineNumberTable ,和 LocalVariableTypeTable 。这些属性对堆栈跟踪(LineNumberTable)和调试器(LocalVariableTable和LocalVariableTypeTable)非常有用。但是,这些完全可选包含在文件中,并且无法保证它们是:

This in itself would be a pain for debuggers and such, so a set of attributes (think metadata for class files) was designed. These include the LocalVariableTable, LineNumberTable, and LocalVariableTypeTable. These attributes are useful for stacktraces (LineNumberTable), and debuggers (LocalVariableTable and LocalVariableTypeTable). However, these are completely optional to include in files, and there is no guarantee that they are:


LineNumberTable属性是属性表中的可选变长属性

The LineNumberTable attribute is an optional variable-length attribute in the attributes table

其余属性也是如此。

此外,大多数编译器默认情况下除了LineNumberTable之外不会产生任何东西,所以即使可能,你也不会运气。

Additionally, most compilers do not produce anything but the LineNumberTable by default, so you'd be out of luck even if it was possible.

基本上,对于开发人员而言,拥有 getFieldName(object)会非常令人沮丧(这对于局部变量首先是不可能的) ),只有当这些属性存在时才有效。

Basically, it would be quite frustrating for developers to have a getFieldName(object) (which wouldn't be possible in the first place for local variables), and only have it work when those attributes are present.

因此,在可预见的将来,使用 getField 使用Strings会遇到困难。无耻的插件: IntelliJ 似乎很好地处理了具有反射的重构:编写了Minecraft mods以及我知道感觉,并且可以说IntelliJ大大减少了重构工作。但对于大多数现代IDE来说也是如此:我确信大型企业Eclipse,Netbeans 已经实施了良好的重构系统。

So you are stuck for the foreseeable future with using getField with Strings. Shameless plug: IntelliJ seems to handle refactors with reflection quite well: having written Minecraft mods as well I know the feeling, and can say that work in refactoring is significantly reduces by IntelliJ. But the same is probably true for most modern IDEs: I'm sure the big players, Eclipse, Netbeans et al. have well-implemented refactoring systems in place.

这篇关于获取字段的名称的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆