12

I'm currently working with a specialized, interpreted, programming language implemented in Java. As a very small part of the language, I'd like to add the ability to make calls into Java. Before I dive into all of the nitty-gritty of reflection, I was wondering if anyone knew of a general library for doing the "back-end" part of invoking Java code reflectively.

That is, I parse a string (I define the grammar) into some data structure that represents a Java method call (or constructor, or field access) and then pass that data structure to this library that invokes the call and returns the result. In particular, I'd like it to already handle all the edge cases that I don't want to figure out:

  • Automagically pick the right method based on the types of arguments (like an intelligent Class.getDeclaredMethod())
  • Handle distinction between arrays and normal object references
  • etc

I've spent a little time looking at the implementations of dynamic languages on the JVM, but these are generally much more complicated than I'm looking for, or highly optimized for the particular language.

Another option is to convert my grammar into a string in some dynamic language and invoke it with Rhino or something, but that's a little more overhead than I'm looking for.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Dave Ray
  • 39,616
  • 7
  • 83
  • 82

11 Answers11

7

Try the FEST Reflection module. It's a fluent way to do Java reflection. For example:

 String name = method("get").withReturnType(String.class)
                         .withParameterTypes(int.class)
                         .in(names)
                         .invoke(8);
rjdkolb
  • 10,377
  • 11
  • 69
  • 89
flicken
  • 15,443
  • 4
  • 29
  • 29
7

Just a comment to your own answer; actually beanutils has support for getting "a close match" given a set of parameters. See getMatchingAccessibleMethod()

BeanUtils is really powerful and has lots of utility methods for inspecting classes. The same support is naturally available for constructors.

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
Bent André Solheim
  • 1,091
  • 7
  • 10
5

If you're looking for simplicity, I have created a simple library called jOOR in order to facilitate access to the reflection API in Java. It supports the most essential actions without building up a huge API. Here's an example of what jOOR code looks like:

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 substring() method
.call("toString")      // Call toString()
.get()                 // Get the wrapped object, in this case a String
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
2

Take a look at Java's scripting support; I believe it will help you tackle your problem.

alex
  • 5,213
  • 1
  • 24
  • 33
  • Nope. I'm looking for something with a method like "Object invoke(Object object, String nameOfMethod, Object[] args)" that finds the right method (taking inheritance and type conversion into account) and calls it. Java scripting just let's me evaluate strings in an existing scripting language. – Dave Ray Dec 13 '08 at 01:12
  • Well, Java scripting does more than letting you invoke scripting languages from Java, if I'm not mistaken- it provides mechanisms to let scripting code interact with Java objects (referred as Binding in the docs), which looks very similar to what you are trying to do. – alex Dec 13 '08 at 01:57
  • ... at least, taking a look at existing scripting implementations should help you – alex Dec 13 '08 at 01:58
  • Thanks Alex. I was able to build an acceptable solution (in terms of engineering work, anyway) using your suggestions. I'll post what I came up with when I'm not watching the kids. :) – Dave Ray Dec 13 '08 at 20:07
  • hehe, I wasn't advocating the solution you choose, but I'm glad it worked for you :) – alex Dec 14 '08 at 19:46
2

Have a look at Apache Commons BeanUtils

1

I would strongly consider also having a look at springs ReflectionUtils class. Very powerful reflection handling.

Roman
  • 7,933
  • 17
  • 56
  • 72
1

TO raise this from the dead:

invoke(Object object, String methodName, Object[] args) 

Apache Commons lang has exactly that method. MethodUtils#invoke

flicken
  • 15,443
  • 4
  • 29
  • 29
Hexren
  • 101
  • 1
  • 3
1

I have started to create a library com.lexicalscope.fluent-reflection:fluent-reflection which integrates with hamcrest and lambdaj

You can write code like this; which calls all the post construct annotated methods in a class:

forEach(
   object(subject).methods(annotatedWith(PostConstruct.class)),
   ReflectedMethod.class).call();

Blog post here: http://www.lexicalscope.com/blog/category/software-projects/fluent-reflection/

Documentation here: http://fluent-reflection.lexicalscope.com/

You can get it from maven central here: http://repo1.maven.org/maven2/com/lexicalscope/fluent-reflection/fluent-reflection/

It has some basic features missing at the moment, like access to fields, but it works for methods. It will probably take a while to get to a really feature stable point (like a year or two), as I am only working on it occasionally. But it is developed to quite a high quality standard (I hope) and it is opensource so you can basically use it as it is now if it has all the features you need (you just might have to adjust your code a bit if you want to use newer versions that are released). I am using it in some production code at them moment.

It is designed to be quite extensible, so you can plugin in strategies to find the methods you want in a loosely coupled (compositional) style. So if it doesn't have the exact method lookup strategy you want, hopefully it is easy to add it.

lexicalscope
  • 7,158
  • 6
  • 37
  • 57
  • That looks really powerful. Do you also have 1-2 more simple examples? – Lukas Eder Dec 29 '11 at 19:18
  • And example of selecting all the get methods: object(subject).methods(callableHasNameStartingWith("get"). and(callableHasNoArguments()).and(not(callableHasVoidReturn()))); – lexicalscope Jan 03 '12 at 14:08
0

I ended up going with Alex's suggestion. BeanUtils helps a lot for beans, but I don't want to work solely with Beans. FEST looks really cool and I've bookmarked it for further study, but like BeanUtils, it doesn't appear to solve what I consider to be the difficult problem here. Namely, given a method name and list of arguments, pick the method that best "fits" the arguments. If a method takes a float and I have a double, it should be smart enough to not reject that method because the signature doesn't match exactly.

Obviously, scripting languages built on the JVM solve this problem, but in a much more complicated way than I need due to language-specific optimizations. So, since this is a minor and experimental feature, I've chosen an expeditious solution using the scripting engine support (JavaScript, in particular) in Java 1.6. Here's the basic idea:

private ScriptEngine engine = ... initialize with JavaScript engine ...

private Object invoke(Object object, String methodName, Object[] args) 
   throws RhsFunctionException
{
   // build up "o.method(arg0, arg1, arg2, ...)"
   StringBuilder exp = new StringBuilder("o." + methodName);
   engine.put("o", object);
   buildArgs(arguments, exp);

   try {
      return engine.eval(exp.toString());
   }
   catch (ScriptException e) {
      throw new RhsFunctionException(e.getMessage(), e);
   }
}

private void buildArgs(Object[] args, StringBuilder exp)
{
   // Use bindings to avoid having to escape arguments
   exp.append('(');
   int i = 0;
   for(Symbol arg : args) {
         String argName = "arg" + i;
         engine.put(argName, arg);
         if(i != 0) {
            exp.append(',');
         }
         exp.append(argName);
         ++i;
   }
   exp.append(')');
}

There's obviously a bit more to it, but this is the basic idea. I don't really like building up a string and evaluating it, but by using the bindings suggested by Alex, I avoid most of the pitfalls around escaping. Furthermore, I have a clean, simple interface that I can swap out with a "real" implementation if it proves necessary.

Any feedback or alternate solutions are more than welcome.

Dave Ray
  • 39,616
  • 7
  • 83
  • 82
0

There is the reflections project, which I believe the most up-to-date utility reflections library with Java 8 support compared to others resorts listed hereabove and ultimately the best way to do some advanced reflection actions as of March 2020.

It reads:

Released org.reflections:reflections:0.9.12 - with support for Java 8
...
Reflections library has over 2.5 million downloads per month from Maven Central, and is being used by thousands of projects and libraries. We're looking for maintainers to assist in reviewing pull requests and managing releases, please reach out.
...
Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project.

Used in conjunction with Java Standard Reflection, it should satisfy all your needs.

improbable
  • 2,308
  • 2
  • 15
  • 28
0

I wrote and open-sourced this code after reading this thread, maybe you can find it useful.

https://github.com/yclian/Reflects.java/blob/master/src/test/java/my/jug/reflects/ReflectsTest.java

It's inspired by Guava, so you can use Predicate to filter the methods you like.

yclian
  • 1,490
  • 14
  • 22