I am the founder and CEO of Data Geekery GmbH, located in Zurich, Switzerland. With our company, we have been selling database products and services around Java and SQL since 2013. Ever since my Master's studies at EPFL in 2006, I have been fascinated by the interaction of Java and SQL. Most of this experience I have obtained in the Swiss E-Banking field through various variants (JDBC, Hibernate, mostly with Oracle). I am happy to share this knowledge at various conferences, JUGs, in-house presentations and on our blog. Lukas is a DZone MVB and is not an employee of DZone and has posted 224 posts at DZone. You can read more from them at their website. View Full User Profile

A neater way to use reflection in Java

01.12.2012
| 29990 views |
  • submit to reddit

Reflection in Java really feels awkward. The java.lang.reflect API is very powerful and complete, and in that sense also very verbose. Unlike in most scripting languages, there is no convenient way to access methods and fields dynamically using reflection. By convenient, I mean things like this

// PHP
$method = 'my_method';
$field  = 'my_field';

// Dynamically call a method
$object->$method();

// Dynamically access a field
$object->$field;

Or even better

// JavaScript
var method   = 'my_method';
var field    = 'my_field';

// Dynamically call a function
object[method]();

// Dynamically access a field
object[field];

For us Java guys, this is something we can only dream of. We would write this

String method = "my_method";
String field  = "my_field";

// Dynamically call a method
object.getClass().getMethod(method).invoke(object);

// Dynamically access a field
object.getClass().getField(field).get(object);

Obviously, this doesn’t take care of NullPointerExceptions, InvocationTargetExceptions, IllegalAccessExceptions, IllegalArgumentExceptions, SecurityExceptions, primitive types, etc. In an enterprise world, things need to be safe and secure, and the Java architects have thought of all possible problems that could arise when using reflection. But in many cases, we know what we’re doing and we don’t care about most of those features. We’d prefer the less verbose way.

That’s why I have created another sibling in the jOO* family: jOOR (Java Object Oriented Reflection). While this is not a killer libary, it might be useful for 1-2 developers out there looking for a simple and fluent solution. Here’s an example I have recently encountered on stack overflow, where jOOR might fit in just perfectly:

// Classic example of reflection usage
try {
  Method m1 = department.getClass().getMethod("getEmployees");
  Employee employees = (Employee[]) m1.invoke(department);

  for (Employee employee : employees) {
    Method m2 = employee.getClass().getMethod("getAddress");
    Address address = (Address) m2.invoke(employee);

    Method m3 = address.getClass().getMethod("getStreet");
    Street street = (Street) m3.invoke(address);

    System.out.println(street);
  }
}

// There are many checked exceptions that you are likely to ignore anyway 
catch (Exception ignore) {

  // ... or maybe just wrap in your preferred runtime exception:
  throw new RuntimeException(e);
}

And the same example using jOOR:

Employee[] employees = on(department).call("getEmployees").get();

for (Employee employee : employees) {
  Street street = on(employee).call("getAddress").call("getStreet").get();
  System.out.println(street);
}

See the full Stack Overflow question here:

http://stackoverflow.com/questions/4385003/java-reflection-open-source/8672186

Another example:

String world = 
on("java.lang.String")  // Like Class.forName()
 .create("Hello World") // Call the most specific matching constructor
 .call("substring", 6)  // Call the most specific matching method
 .call("toString")      // Call toString()
 .get()                 // Get the wrapped object, in this case a String

Get jOOR for free here:

http://code.google.com/p/joor/

 

From http://lukaseder.wordpress.com/2011/12/29/a-neater-way-to-use-reflection-in-java/

Published at DZone with permission of Lukas Eder, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Andy Till replied on Thu, 2012/01/12 - 7:58am

Nice, I actually prefer the jOOR examples to the javascript ones.  There is something ugly about map access for everything.

Wladimir Mangelardo replied on Thu, 2012/01/12 - 9:46am

Very good! I know a similar library, called Mirror (http://projetos.vidageek.net/mirror/mirror/).

Xavier Dury replied on Thu, 2012/01/12 - 10:14am

You could also try using FEST-Reflect

Arnaud Des_vosges replied on Thu, 2012/01/12 - 12:02pm

It's possible to use a "helper" interface that is not implemented by the target object, but can be used to make dynamic calls easier:
    public static  INTF createProxy(final TARGET target, Class(INTF) interf) {
        
        final Class targetClass = target.getClass();
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Method targetMethod = targetClass.getMethod(
                        method.getName(), method.getParameterTypes());
                return targetMethod.invoke(target, args);
            }
        };
        return (INTF)Proxy.newProxyInstance(
                interf.getClassLoader(),
                new Class[]{interf},
                handler
        );
  }

interface DepartmentHelper {
    Employee[] getEmployees();
     Address getAddress();
}

Object anyObject = ...
DepartmentHelper department = createProxy(anyObject, DepartmentHelper.class);
Employee[] employees = department .getEmployees();
Address  addr = department .getAddress();

Thomas Berger replied on Fri, 2012/01/13 - 4:32am

Aren't you missing a final "get" on the fourth line of your Employee example using jOOR ?

I think the following line
Street street = on(employee).call("getAddress").call("getStreet");

should be

Street street = on(employee).call("getAddress").call("getStreet").get();

Lukas Eder replied on Fri, 2012/01/13 - 5:20am in response to: Thomas Berger

You are right, fixed. Thanks!

Lukas Eder replied on Fri, 2012/01/13 - 5:20am in response to: Arnaud Des_vosges

That's very nice, I had never thought of that. With your permission, I'd like to add that to jOOR!

Arnaud Des_vosges replied on Fri, 2012/01/13 - 6:56am in response to: Lukas Eder

you're welcome :)

Sandeep Bhandari replied on Fri, 2012/01/13 - 8:24am

That is really a nice way of having reflection implemented in a java application

Martijn Verburg replied on Sat, 2012/01/14 - 11:14am

Have you looked at using MethodHandles in Java 7? It's basically a way of doing type safe reflection without having to break the security manager...

Lukas Eder replied on Sat, 2012/01/14 - 1:26pm in response to: Martijn Verburg

MethodHandles look like a nice addition to the java.lang API. Unfortunately, I haven't upgraded to Java 7 yet...

Lukas Eder replied on Sat, 2012/01/14 - 1:59pm in response to: Arnaud Des_vosges

Using the InvocationHandler and Proxy along with jOOR looks great! Your method can be wrapped like this:

    @SuppressWarnings("unchecked")
    public <P> P as(Class<P> proxyType) {
        final InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return on(object).call(method.getName(), args).get();
            }
        };
        
        return (P) Proxy.newProxyInstance(proxyType.getClassLoader(), new Class[] { proxyType }, handler);
    }

Which can then be used in jOOR like this:

Employee[] employees = on(department).as(DepartmentHelper.class).getEmployees();
 
for (Employee employee : employees) {
  Street street = on(employee).as(EmployeeHelper.class).getAddress().getStreet();
  System.out.println(street);
}

 

Arnaud Des_vosges replied on Mon, 2012/01/16 - 11:17am in response to: Lukas Eder

Nice result!

It's also possible to automatically wrap the result of the method (using the declared return type of the helper method) and also unwrap arguments if needed. That would implement a kind of "membrane" pattern. (Primitives and non-interface types would not be wrapped. Also wrapping would be avoided if the returned object directly implements the declared return type of the helper.)

interface DepartmentHelper {

      List<EmployeeHelper> getEmployees(); // instead of List<Employee> getEmployees()
      void add(EmployeeHelper employee); //  instead of add(Employee)
...
}

List<EmployeeHelper> employees = on(department).as(DepartmentHelper.class).getEmployees(); // wrap returned intf
on(otherDepartment).add(employees.get(0)); // unwrap arg

Lukas Eder replied on Tue, 2012/01/17 - 1:07pm in response to: Arnaud Des_vosges

Hi Arnaud,

Feel free to provide a patch! :-)

Cheers,
Lukas

Arnaud Des_vosges replied on Thu, 2012/01/19 - 6:22am in response to: Lukas Eder

ok!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.