-1

Using byte-buddy is that possible to reference field name as string. Here is what I m trying.

public class MyClass {
    public int x;
    public int y;
}

public String getMethodName() {
    Class clazz = MyClass.class;
    return clazz.getFields()[0].getName();
}

Here I will not get field x every time at position[0], so can not rely on that.

I have not used byte-buddy before.I searched questions present here related byte-buddy,also searched in documentation,but not found this particular type of example.

LaraFlow
  • 352
  • 5
  • 15
  • Eh? What do you want to accomplish? If you wanted to be able to write `MyClass::myField`, why wouldn't you just write `"myField"`...? – Michael Jul 31 '19 at 12:54
  • I want it to dynamically, say I do not know that name as string at runtime. – LaraFlow Jul 31 '19 at 13:01
  • So then `MyClass::myField` is not a good example of what you want – Michael Jul 31 '19 at 13:01
  • 1
    Why do you think you need byte buddy for this at all? You should be able to accomplish it using standard reflection e.g. `MyClass.getDeclaredField(something)` – Michael Jul 31 '19 at 13:03
  • Yes, I found similar like , but for that i will need "something" as string. What I want is String fieldname = MyClass.getDeclaredField(MyClass_fieldname). – LaraFlow Jul 31 '19 at 13:08
  • I don't understand the problem. What type do you suppose `MyClass_fieldname` will be, if not a string? – Michael Jul 31 '19 at 13:10
  • It is fieldname of course as String if I use getDeclaredField, but not hard coded. – LaraFlow Jul 31 '19 at 13:12
  • Still do not understand the problem. You can call `MyClass.getDeclaredField` *with or without* a hardcoded string. – Michael Jul 31 '19 at 13:20
  • According to documentation public Field[] getDeclaredFields() returns Field array. What I can do is getDeclaredFields()[0].getName(), but again here it is not sure that getDeclaredFields()[0] is same field that I assumed, because it is not gauranteed that getDeclaredFields() return every time all fields in same order. – LaraFlow Jul 31 '19 at 13:25
  • You already said, you have the name of the field in a variable called `MyClass_fieldname`. You do not and should not need to get every field and arbitrarily select the first one – Michael Jul 31 '19 at 13:27
  • No,I do not have MyClass_fieldname as string, It is something that I am missing to achieve what I want. – LaraFlow Jul 31 '19 at 13:33
  • Then why did you say "What I want is String fieldname = MyClass.getDeclaredField(MyClass_fieldname)"...? Can you see why I'm confused? You do not seem able to describe the problem. How can we help you if you can't do that? – Michael Jul 31 '19 at 13:34
  • Ok, sorry, if it miss guided you. I want to have "field name as String". I should say MyClass.getDeclaredField(==Some Magic here==). However I do not need even Field, I need just field name. – LaraFlow Jul 31 '19 at 13:44
  • How do you plan to magically distinguish this field from any other field? – Michael Jul 31 '19 at 13:46
  • Hypothetical: Suppose I tell you I am looking for a person. I don't know their name, what they look like, or where they live. But I still insist I need to find them. What strategy do you use? – Michael Jul 31 '19 at 13:48
  • Yes, that is not possible if I do not have any reference, or identity. I am trying to point field the way we use getSimpleName(). MyClass.class.getSimpleName() anywhere will give me "MyClass". Now if I change name of class MyClass to YourClass, then method getSimpleName() will give me "YourClass". So for field x in above example MyClass.x.getName() ? – LaraFlow Jul 31 '19 at 14:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/197286/discussion-between-laraflow-and-michael). – LaraFlow Jul 31 '19 at 15:02

2 Answers2

1

It is slightly unclear what you want, but my best guess is that you are referring to reflection.

Reflection gets its name from the idea that the code "looks at its reflection in a mirror", i.e. code looking at itself. The java reflection API is incredibly powerful, and allows you to do things possible impossible using other techniques, but it has major drawbacks.

For example:

public class MyClass {
    public int x;
}

public String getMethodName() {
    Class clazz = MyClass.class;
    return clazz.getFields()[0];
}

public void setField(int newValue) {
    Class clazz = MyClass.class;
    clazz.getFields()[0].setInt(newValue);
}

The above code: - defines a basic class - provides a method to get the name of the first field - provides a method to set the value of this field.

This seems to be what you are asking about.

However, there are serious downsides to using reflection.

  • It is very slow, up to 1000x slower, as the JVM is less able to make optimisations, since it has less information about the data it is working with at compile time.
  • It introduces the possibility for very nasty bugs. Once you open this can of worms, you can no longer confidently make assumptions about your code that you would before. If you have a class with a private variable with no setters, you might assume its value cannot be changed. Using reflection, it can.
  • It ignores Java's type checking system. This is one reason for the slowness mentioned above, since type checking must be done at runtime rather than compile-time. However, it also opens you up to type errors in a major way again, the entire thing Java's type system tries to save you from.

Because of this, reflection should only be used when there are literally no alternatives, for example, making a Json parsing library, writing an ORM system, etc. In other situtations, I have found that generally problems that seem to be reflection problems are actually abstraction problems.

Perhaps if, instead of getting a field by its String name, you could create an interface called ContainsMyField with a method called getMyField(), and any class that you expect to have this field should implement this interface. This option is much cleaner, faster, and safer.

cameron1024
  • 9,083
  • 2
  • 16
  • 36
  • You are getting me. I m trying to make question more clear. Solution you provided clazz.getFields()[0]; is ok when you have only one field, but when you have more than one field, it is not sure that you will get same field every time, or on every JVM implementation. According to Oracle documentation it is not gauranteed. – LaraFlow Jul 31 '19 at 13:18
  • 1
    Yes, Java does not guarantee that `clazz.getFields()` returns the fields in the order they appear in the source code. This is a reason why reflection seen as clunky. You can call `clazz.getField("fieldName")` if you know the name of the field in advance. However, if you do not know the name of the field, and you can't rely on it being in a particular position, realistically you can't get your data, since you haven't provided enough information to locate it. – cameron1024 Jul 31 '19 at 13:22
0

It is not possible for Fields to get name as String of the field this way, using reflection.

LaraFlow
  • 352
  • 5
  • 15