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.
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.
How about using lombok annotation @FieldNameConstants
@FieldNameConstants
public class Mod {
public ItemLinkTool linkTool;
}
...
String fieldName = Mod.Fields.linkTool; //fieldName == "linkTool"
With this feature we don't need to maintain code for getting field names (lombok does it for us). After deleting a field compiler will complain about it's usage.
Note that this feature is marked as experimental.
Field[] fields = YourClassName.class.getFields();
returns an array of all public variables of the class.
getFields() return the fields in the whole class-heirarcy. If you want to have the fields defined only in the class in question, and not its superclasses, use getDeclaredFields(), and filter the public ones with the following Modifier approach:
Modifier.isPublic(field.getModifiers());
The YourClassName.class literal actually represents an object of type java.lang.Class. Check its docs for more interesting reflection methods.
The Field class above is java.lang.reflect.Field. You may take a look at the whole java.lang.reflect package.
https://docs.oracle.com/javase/tutorial/reflect/class/classMembers.html also has charts for locating methods and constructors.

obj = obj.getClass().getSuperclass().cast(obj);
This line does not do what you expect it to do. Casting an Object does not actually change it, it just tells the compiler to treat it as something else.
E.g. you can cast a List to a Collection, but it will still remain a List.
However, looping up through the super classes to access fields works fine without casting:
Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
// do something with current's fields
current = current.getSuperclass();
}
BTW, if you have access to the Spring Framework, there is a handy method for looping through the fields of a class and all super classes:
ReflectionUtils.doWithFields(baseClass, FieldCallback)
(also see this previous answer of mine: Access to private inherited fields via reflection in Java)
getDeclaredFields() gives you all fields on that Class, including private ones.
getFields() gives you all public fields on that Class AND it's superclasses.
If you want private / protected methods of Super Classes, you will have to repeatedly call getSuperclass() and then call getDeclaredFields() on the Super Class object.
Nothing here isn't clearly explained in the javadocs
You have to use reflection:
- Use
Class.getField()to get aFieldreference. If it's not public you'll need to callClass.getDeclaredField()instead - Use
AccessibleObject.setAccessibleto gain access to the field if it's not public - Use
Field.set()to set the value, or one of the similarly-named methods if it's a primitive
Here's an example which deals with the simple case of a public field. A nicer alternative would be to use properties, if possible.
import java.lang.reflect.Field;
class DataObject
{
// I don't like public fields; this is *solely*
// to make it easier to demonstrate
public String foo;
}
public class Test
{
public static void main(String[] args)
// Declaring that a method throws Exception is
// likewise usually a bad idea; consider the
// various failure cases carefully
throws Exception
{
Field field = DataObject.class.getField("foo");
DataObject o = new DataObject();
field.set(o, "new value");
System.out.println(o.foo);
}
}
Class<?> actualClass=actual.getClass();
Field f=actualClass.getDeclaredField("name");
The above code would suffice .
object.class.getField("foo");
Unfortunately the above code didn't work for me , since the class had empty field array.
You should pass the object to get method of the field, so
import java.lang.reflect.Field;
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object value = field.get(object);
Like answered before, you should use:
Object value = field.get(objectInstance);
Another way, which is sometimes prefered, is calling the getter dynamically. example code:
public static Object runGetter(Field field, BaseValidationObject o)
{
// MZ: Find the correct method
for (Method method : o.getMethods())
{
if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3)))
{
if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
{
// MZ: Method found, run it
try
{
return method.invoke(o);
}
catch (IllegalAccessException e)
{
Logger.fatal("Could not determine method: " + method.getName());
}
catch (InvocationTargetException e)
{
Logger.fatal("Could not determine method: " + method.getName());
}
}
}
}
return null;
}
Also be aware that when your class inherits from another class, you need to recursively determine the Field. for instance, to fetch all Fields of a given class;
for (Class<?> c = someClass; c != null; c = c.getSuperclass())
{
Field[] fields = c.getDeclaredFields();
for (Field classField : fields)
{
result.add(classField);
}
}