views:

235

answers:

3

I have a Class<? extends Annotation> and tried calling newInstance() but Java yelled at me for the obvious reason that I can't instantiate an interface. But I know frameworks like EasyMock are perfectly capable of instantiating interfaces. What would it take to get a completely dumb Annotation instance out of my Class?

+2  A: 

You can't create an instance of a class that's not fully specified.

To illustrate, calling newInstance() on a class of type Class<Object> would definately create an Object, but calling newInstance() on a class of type Class<?> would leave the compiler wondering which class out of the entire universe of possibilities it should construct.

Just because you have narrowed the field down a bit by specifying that instead of just ?, you want a ? that extends Annotation doesn't mean you've actually named a particular class to construct. ? extends Annotation just means "some class that extends Annotation" Without naming the exact class, the ClassLoader cannot figure out which constructor to call, because there is no limit to the number of classes that might extend Annotation.

EasyMock doesn't instantiate Interfaces. I'm not familiar with the framework, but it likely instantiates java.lang.Object(s) which extend the desired interface, or it instantiates some sort of "behind the scenes" framework class which was generated with an "implements interface" clause in the class definition. Interfaces don't have a default constructor.

Edwin Buck
I believe EasyMock uses CGLIB. Mockito uses CGLIB. CGLIB is a library that let you create a proxy object. It is faster than Java proxy since it creates/manipulate bytecode.
mjlee
EasyMock seems to generate a class with a name similar to $Proxy0. The $ sign typically represents an inner / generated class name, and the 0 probably is the internal mocked class number according to EasyMock's internal architecture. So easy mode still creates a class, not an interface; however, it creates a class that obviously implements the interface.
Edwin Buck
+1  A: 

Mock frameworks do not instantiate interfaces, they build classes that implement them on the fly at runtime. You may find this javadoc enlightening for what you want to do!

Affe
+1  A: 

Thanks to Affe for pointing me the right direction - I'd comment on his answer but then I wouldn't be able to format the solution:

Annotation annotation = (Annotation) Proxy.newProxyInstance(
  clazz.getClassLoader(),
  new Class[] { Annotation.class },
  new InvocationHandler() {
    @Override public Object invoke(Object proxy, Method method, Object[] args) {
      return clazz; // only getClass() or annotationType() should be called.
    }
  });
works like a charm.

Steve
I can't figure out what possible _good_ this broken Annotation instance could be doing you. It's like I asked for a burger and got a photocopy of an old black-and-white photograph of a ham sandwich. Explain?
Kevin Bourrillion
I'm working with Guice code that deals with binding annotations. Except for `@Named`, only `annotationType()` and maybe `getClass()` are ever called on the `Annotation` s I pass to the method I'm calling. So as long as my `Annotation` can mimic those methods, it'll work fine.
Steve