I made a Dynamic Proxy to be the middle man when handling specific methods in a class. I'm doing this to avoid having to override every single method in each of the interfaces that I need to take control of.
Waffley bit that nobody will understand or care about (but may add more context to the question):
In the example I am going to give, I've tried to make it generic so you can compile it to test and run yourself, but in the real situation, I have something like this:
interface CommandSender
interface ConsoleCommandSender extends CommandSender
interface Player extends CommandSender
If I were to make a proxy of a ConsoleCommandSender
instance, the resulting proxy SHOULD be castable to a CommandSender
. In reality, ConsoleCommandSender
doesn't list all of its interfaces with getInterfaces()
and this happens:
java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender
The Player class does not have this issue, and is always castable to CommandSender
.
The real question:
So, using the following code as a starting point, how can one successfully cast the proxy denoted by myProxy
to the format desired without having to worry about the ClassCastException
?
The following code will successfully compile and run, but hopefully you understand what I'm getting at by casting to a List
rather than an ArrayList
.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
public class ProxyClass implements InvocationHandler {
private Object classProxy;
public static void main(String[] args) {
// Example declaration
// (I know the proxy should really be cast as an ArrayList
// but this is my point, it SHOULD work anyway)
ArrayList methodObject = new ArrayList<String>();
List<String> myProxy = (List<String>)ProxyClass.newInstance(methodObject, false);
// Example usage
myProxy.add("Hello World!");
System.out.println(myProxy.get(0));
}
public static Object newInstance(Object proxy, boolean silent) {
return Proxy.newProxyInstance(
proxy.getClass().getClassLoader(),
proxy.getClass().getInterfaces(),
new ProxyClass(proxy));
}
private ProxyClass(Object proxy) {
this.classProxy = proxy;
}
// Is called whenever a method is invoked
public Object invoke(Object p, Method m, Object[] args) throws Throwable {
return m.invoke(classProxy, args);
}
}
On another thread I made about the preliminary part of this issue, one guy commented saying I could use the <T>
variable to add another valid interface to the list. I didn't really understand how to implement this though, but it seemed like a good start.