I'm using some Java code which produces the following interfaces. This code is non-modifiable.
interface A1 {
public void run();
}
interface A2 {
public void run();
}
...
interface A24 {
public void run();
}
I'm having a class cast error with the following code. How would I dynamically build an adapter to my interface?
interface ARunnable {
public void run();
}
public void someMethod() {
// getARunnables() returns a list of A1, A2, ... A24
List<ARunnable> runnables = (List<ARunnable>)getARunnables();
for (ARunnable a : runnables) {
a.run();
}
}
Since the interfaces can't be modified to extend java.lang.Runnable, an option would be to use java.lang.reflect.Proxy to build up instances of Runnable that delegate to your A1, A2... interfaces.
It's not trivial, but take a look at this example using java.lang.reflect.Proxy. The sample simply delegates to a delegate object based on method name.
public class ProxyTest
{
public static void main(String... args)
{
List<?> instances = Arrays.asList(new A1());
List<ARunnable> runnableInstances = new ArrayList<ARunnable>(instances.size());
for (Object instance : instances)
{
ARunnable runnableInstance = (ARunnable)Proxy.newProxyInstance(
ARunnable.class.getClassLoader(),
new Class<?>[] {ARunnable.class},
new RunnableWrapper(instance));
runnableInstances.add(runnableInstance);
}
//Now we have a list of ARunnables!
//Use them for something
for (ARunnable runnableInstance : runnableInstances)
{
runnableInstance.run();
}
}
private static class RunnableWrapper implements InvocationHandler
{
private final Object instance;
public RunnableWrapper(Object instance)
{
this.instance = instance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
//Ensure that your methods match exactly or you'll get NoSuchMethodExceptions here
Method delegateMethod = instance.getClass().getMethod(method.getName(), method.getParameterTypes());
return(delegateMethod.invoke(instance, args));
}
}
public static class A1
{
public void run()
{
System.out.println("Something");
}
}
public static interface ARunnable
{
public void run();
}
}
Also I would recommend you fix the line
List<ARunnable> runnables = (List<ARunnable>)getARunnables();
That type safety warning you should not ignore. That list of objects does not actually contain ARunnables, hence the ClassCastException.