Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Metaprogramming

I'm working on my first real project with Java. I'm beginning to get comfortable with the language, although I have more experience with dynamic languages.

I have a class that behave similar to the following:

class Single
{
    public void doActionA() {}
    public void doActionB() {}
    public void doActionC() {}
}

And then I have a SingleList class that acts as a collection of these classes (specifically, it's for a 2D Sprite library, and the "actions" are all sorts of transformations: rotate, shear, scale, etc). I want to be able to do the following:

class SingleList
{
    public void doActionA() {
        for (Single s : _innerList) {
            s.doActionA();
        }
    }

    ... etc ...
}

Is there any way to simply defer a method (or a known list of methods) to each member of the inner list? Any way without having to specifically list each method, then loop through each inner member and apply it manually?

To make things a bit harder, the methods are of varying arity, but are all of return type "void".

like image 535
efritz Avatar asked Jan 15 '12 07:01

efritz


1 Answers

Unfortunately Java does not readily support class creation at runtime, which is what you need: the SingleList needs to be automatically updated with the necessary stub methods to match the Single class.

I can think of the following approaches to this issue:

  1. Use Java reflection:

    • Pros:
      • It's readily available in the Java language and you can easily find documentation and examples.
    • Cons:
      • The SingleList class would not be compatible with the Single class interface any more.
      • The Java compiler and any IDEs are typically unable to help with methods called via reflection - errors that would be caught by the compiler are typically transformed into runtime exceptions.
      • Depending of your use case, you might also see a noticeable performance degradation.
  2. Use a build system along with some sort of source code generator to automatically create the SingleList.java file.

    • Pros:
      • Once you set it up you will not have to deal with it any more.
    • Cons:
      • Setting this up has a degree of difficulty.
      • You would have to separately ensure that the SingleList class loaded in any JVM - or your IDE, for that matter - actually matches the loaded Single class.
  3. Tackle this issue manually - creating an interface (e.g. SingleInterface) or a base abstract class for use by both classes should help, since any decent IDE will point out unimplemented methods. Proper class architecture would minimize the duplicated code and your IDE might be able to help with generating the boilerplate parts.

    • Pros:
      • There is no setup curve to get over.
      • Your IDE will always see the right set of classes.
      • The class architecture is usually improved afterwards.
    • Cons:
      • Everything is manual.
  4. Use a bytecode generation library such as Javassist or BCEL to dynamically generate/modify the SingleList class on-the-fly.

    • Pros:
      • This method is extremely powerful and can save a lot of time in the long term.
    • Cons:
      • Using bytecode generation libraries is typically not trivial and not for the faint-hearted.
      • Depending on how you write your code, you may also have issues with your IDE and its handling of the dynamic classes.
like image 153
thkala Avatar answered Sep 20 '22 18:09

thkala