spinjector February 2016

Java Indirect Access to Variables by Name at Runtime?

This question has multiple parts, and will all make sense in the last part:

  1. Is it possible to programmatically list any programmer-defined variables in a Java class at runtime..?

    I recently wrote a utility procedure in VB.Net that lists all the forms in my project by name, so I can pick one to run from a listbox (just for development purposes). With help from elsewhere on StackOverflow, I was able to pin the following bit of code together, and this example is pinned together even more for illustrative purposes...

        System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes(n).BaseType.FullName
    

    Can something similar be done in Java to list variable names..? That being MyInteger, MyString, or MyObject, for example. It'd be like the function behind the "Locals" window in Visual Studio (but I'm using Eclipse for Java).

  2. Somewhere in the past 20 years, in another programming language, I came across a function called Indirect(String varname). It was used to access a primitive variable by name. And the 'varname' parameter could itself be a variable; it didn't have to be a literal. Here's an example showing its use:

    int N1, N2, N3;
    // N1, N2, & N3 are all zero
    for (int i = 1; i < 4; i++){
        Indirect("N" + i.toString) = 100
    }
    // N1, N2, & N3 are now all 100
    

    Does Java have an equivalent to Indirect(), or is there a way to duplicate the same functionality..?

  3. To glue all this together, and the reason for this entire forum post, is that I have the following procedure that I've written for debugging purposes, that I drop into my classes to output variable values in CSV format during development...

    public String listVars(){
        Object input[] = {var1, var2, var3, var4, var5};    // list of vars
        String output = "";                     // output catcher
        int varCount = input.length;            // get the len        

Answers


radai February 2016

  1. listing class fields/methods at runtime

yes, you can do that, with reflection. see the tutorial here:

for (Field f : getClass().getDeclaredFields()) {
    System.out.println("found " + f);
}
  1. "Indirect" access

yes, using the above mechanism to find the field you wish to altar you can then set its value

Field f = ... //get it from somewhere
f.set(this, "new value");

what you want to achieve sounds very close to the java bean concept. the gist of it is that you keep to a getX()/setX() naming convention for your getter and setter methods, each such pair representing a property called "x" and you can then utilize bean-oriented libraries, such as apache commons beanutils to all all the heavy lifting (that i told you about above) for you, like so:

Employee employee = ...;
String firstName = (String)PropertyUtils.getSimpleProperty(employee, "firstName");
String lastName = (String)PropertyUtils.getSimpleProperty(employee, "lastName");
 ... manipulate the values ...
PropertyUtils.setSimpleProperty(employee, "firstName", firstName);
PropertyUtils.setSimpleProperty(employee, "lastName", lastName);


Boris N February 2016

First, all of Java's reflection api can be found under java.lang.reflect package and that the best way to learn that package is probably java's own trails Reflection Trail

TL;DR

1) It seems after some investigation there is a Field.getName() so that would probably serve you well.

2) There is indeed a way to obtain fields (variables) as well as methods and even constructors. [Specific Trail page][3] The way to do that is through the Field class in the reflect package. An example of this is Field foo = myObject.class.getField("fieldName") or class.getDeclaredField("name") the difference being that the declared version explicitly only looks in that object and also gets the private fields as well.

There are s versions as well class.getDeclaredFields() and class.getFields() that return a Field[]. There are also method and constructor versions of all 4 types (declared, regular, and s (array) of both)

3) A lot of information is accessible from access modifiers (private, public etc.) and through Field.toGenericString() or Field.getModifiers() etc.

As for the implementation, it should be along the lines of Field.getDeclaredFields() combined with Field.getName() and Field.get*() where * is the type (int, long, Object etc). If you need fields from super class and you still want to list the privates then you wold need to recursively apply Class.getSuperclass() with Field.getDeclaredFields(). Additionally Field.toGenericString() if you want a nice long detailed string.

Post Status

Asked in February 2016
Viewed 1,343 times
Voted 13
Answered 2 times

Search




Leave an answer