2

I have a JET Template that is meant to generate code for an interface implementation class. I am having trouble coming up with an executable test class that prints out this generated code because I am unable to get an object for the argument of the generate method created from the JET Template.

I want the test class to work something like this:

/**
 * An executable test class that prints out exemplary generator output
 * and demonstrates that the JET template does what it should.
 */
public class TestClass {
    public static void main(String args[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        String className = "A"; // "A" is the name of the interface in the same package.

        Class c = Class.forName(className);
        Object o = c.newInstance();

        Q2Generator g = new Q2Generator(); // Class created from the JET Template
        String result = g.generate(o);
        System.out.println(result);
    }
}

But obviously, c.newInstance(); doesn't work for an interface. Is there another way I could possibly feed an object of the interface through to the generate method? I need the object of the interface because in the Q2Generator's generate method, it takes information about the method declarations in the interface from the object argument.

I'm not sure if that provides enough context, but if it isn't enough there are more details in another question I asked here: Using JET to generate code: Indenting code

Thanks.

Community
  • 1
  • 1
Jigglypuff
  • 1,433
  • 6
  • 24
  • 38

1 Answers1

4

If I understand what you're trying to do, you should be able to pull it off with dynamic proxying. Here's an example of implementing an interface at runtime without explicitly knowing the interface's type:

import java.lang.reflect.*;

public class ImplementInterfaceWithReflection {
    public static void main(String[] args) throws Exception {
        String interfaceName = Foo.class.getName();
        Object proxyInstance = implementInterface(interfaceName);
        Foo foo = (Foo) proxyInstance;
        System.out.println(foo.getAnInt());
        System.out.println(foo.getAString());
    }

    static Object implementInterface(String interfaceName)
            throws ClassNotFoundException {
        // Note that here we know nothing about the interface except its name
        Class clazz = Class.forName(interfaceName);
        return Proxy.newProxyInstance(
            clazz.getClassLoader(),
            new Class[]{clazz},
            new TrivialInvocationHandler());
    }

    static class TrivialInvocationHandler implements InvocationHandler {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) {
            System.out.println("Method called: " + method);
            if (method.getReturnType() == Integer.TYPE) {
                return 42;
            } else {
                return "I'm a string";
            }
        }
    }

    interface Foo {
        int getAnInt();
        String getAString();
    }
}
Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199