Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get name of a field

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: I'm not looking for a field's class/class name or getting Field from name in String.


EDIT: When I'm looking at it I probably wouldn't need a method to get a field's name, the Field instance (from field's "code name") would suffice. [e.g. Field myField = getField(linkTool)]

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));         }     } } 

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..)

like image 349
monnef Avatar asked Feb 18 '13 20:02

monnef


People also ask

How do I get a field name?

To get field's name, go like that: //use the field object from the example above field. getName(); // it is in String.

What is a field name in Java?

A Java field is a variable inside a class. For instance, in a class representing an employee, the Employee class might contain the following fields: name. position. salary.

What is field name?

Field name means the label or identification of an element of a computer data base that contains a specific item of information, and includes but is not limited to a subject heading such as a column header, data dictionary, or record layout.

Do fields have names?

Many field names refer to current and previous field uses – names like 'The Night Field', 'The Turnip Field', 'The Bulls Paddock', 'The Dairy Field', 'Sheep Walk', 'Fattening Park', 'The Ryegrass', 'Calf Paddock', 'Hen Run', 'Kitchen Field', 'The Drinking Hole Field' and 'Long Meadow' to name just a few.


1 Answers

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

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.

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.

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.

In other words, a class like

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

gets compiled into

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--     } 

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).

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:

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

The same holds for the rest of them.

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

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.

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.

like image 78
Xyene Avatar answered Oct 09 '22 04:10

Xyene