1

Lets say I have a class

class A {
   string name;
   int age;
   string gender;
   //assuming all the constructors, getters and setters are present
}

for purpose of simplicity, lets assume all these members are public and to access them I create an object of that class as follows

A a = new A();

is there a way to access the each member as follows

String string = "age"

a.string

and get the age of the object and so on. similarly, lets say I have a getter and can I access it using

String string = "getAge()";
a.string;

I am an beginner java programmer trying to optimize a code written in swift (needless to say I am a novice in swift), which has a class with more than 50 members and setting/getting each of them in some other module gets very tedious.

Just wondering if this is possible in either of the programming languages. In java I assume something like this might be possible using class reflection, but not very sure.

m1o2
  • 1,549
  • 2
  • 17
  • 27
Hardik Shah
  • 916
  • 1
  • 7
  • 13
  • 6
    Yes, you'll have to use reflection, but this is also, generally speaking, a significant code smell. – Louis Wasserman Mar 02 '16 at 17:26
  • Do change java conventions and expect to assume private variables as public. I would suggest declaring public in the example. – TechCrunch Mar 02 '16 at 17:27
  • 4
    Speaking of code smells: "a class with more than 50 members". – Andy Turner Mar 02 '16 at 17:29
  • 1
    Reflections has API to inspect classes at run time, which includes accessing class fields and its methods. Also, you can call these methods or populate the fields depending your requirements. – Ankur Shanbhag Mar 02 '16 at 17:33
  • @AndyTurner the class is a mapper class to one of the database tables with more than 50 attributes, which I am populating using a dictionary in swift. – Hardik Shah Mar 02 '16 at 17:39

3 Answers3

4

Well, you can use reflection, and do something like:

A a = new A();
Class cls = a.getClass();

//read a method value
String methodName = "getAge";
Method method = cls.getDeclaredMethod(methodName);
int methodReturnedResult = method.invoke(a, null);

//read a field value
String fieldName = "age";
Field field = cls.getDeclaredField(fieldName);
int fieldValue = field.get(a);

This is another example
Java Reflection tutorial

Though it is important to note that reflection wasn't meant for these cases and it isn't considered a good design to use reflection in these scenarios. What you need to do is to use IDE's abilities to generate setters and getters for you automatically.
Which IDE do you use? Most Java IDE's has the ability to generate getters and setters automatically according to the class fields.

This is how you do it in Eclipse, Netbeans, Intellij and in Android Studio.

Community
  • 1
  • 1
m1o2
  • 1,549
  • 2
  • 17
  • 27
  • I use eclipse. What I really wanted to ask was to understand how to dynamically/programatically call the getters/setters. something like the last part of my example. – Hardik Shah Mar 02 '16 at 17:44
  • @HardikShah See my example, it demonstrates exactly that :) – m1o2 Mar 02 '16 at 17:46
1

As explained here (with an example), you can use java reflection to check whether class contains a field and get the value of that field.

Also, making the fields public isn't a good idea, they should be private and accessed only via getters and setters.

Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102
  • ...unless your members are final. Especially if you have final static members. – Huxley Mar 02 '16 at 17:28
  • @Huxley it's a good idea to use accessors even if your members are final. See Effective Java 2nd ed Item 14 "In public classes, use accessor methods, not public fields". It allows you to change the implementation without changing the interface; override the accessor; synchronize access etc. – Andy Turner Mar 02 '16 at 17:30
0

If you have to use reflation, below should work.

Class A

class A {
    String name;
    int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

}

Utility method in your class

public Object get(String methodName, A a) throws Exception {
    Object ret = null;
    if(a != null){
        Class<A> cl = A.class;
        Method method = cl.getDeclaredMethod(methodName);
        ret = method.invoke(a);
    }
    return ret;
}

public void set(String methodName, Object value, A a) throws Exception{
    Class<A> cl = A.class;
    Method method = cl.getDeclaredMethod(methodName, value.getClass());
    method.invoke(a, value);

}

Test it

public void testIt() throws Exception{
    A a = new A();
    set("setName", "xyz", a);
    String name = (String) get("getName",a);
    System.out.println(name);
}

Note: be careful on boxed type i.e. int is represented as Integer. And good amount of null checks.

Jags
  • 799
  • 7
  • 19