当我将动态代理类转换为我想要的对象时,我会有些奇怪。在运行时,在某些条件下,我收到ClassCastException。
为了更好地解释这一点,以下是我想要使用的类/接口的定义。括号已放在任何扩展接口(应该)不相关的地方。
public interface CommandSender (extends Permissible)
public interface ConsoleCommandSender extends CommandSender, (Conversable)
public interface Player extends (HumanEntity, Conversable), CommandSender, (OfflinePlayer, PluginMessageRecipient)
可在此处找到完整的Javadoc:http://jd.bukkit.org/apidocs/org/bukkit/command/CommandSender.html
现在,这是我的代理类的代码:
public class CommandSignsMessagingProxy implements InvocationHandler {
private Object sender;
private Object receiver;
private boolean silent;
public static Object newInstance(Object proxy) {
return newInstance(proxy, proxy, false);
}
public static Object newInstance(Object proxy, boolean silent) {
return newInstance(proxy, proxy, silent);
}
public static Object newInstance(Object sender, Object receiver) {
return newInstance(sender, receiver, false);
}
public static Object newInstance(Object sender, Object receiver, boolean silent) {
return Proxy.newProxyInstance(
sender.getClass().getClassLoader(),
sender.getClass().getInterfaces(),
new CommandSignsMessagingProxy(sender, receiver, silent));
}
private CommandSignsMessagingProxy(Object sender, Object receiver, boolean silent) {
this.sender = sender;
this.receiver = receiver;
this.silent = silent;
}
// Is called whenever a method is invoked
public Object invoke(Object p, Method m, Object[] args) throws Throwable {
Object result = null;
try {
String name = m.getName();
// If the receiver is being sent a message, only do so if the silent flag is not set
if (name == "sendMessage" || name == "sendRawMessage") {
if (!silent && receiver != null)
result = m.invoke(receiver, args);
} else {
result = m.invoke(sender, args);
}
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("Unexpected invocation exception: " + e.getMessage());
}
return result;
}
}
这是一个完全可用的类实例:
Player proxy = (Player)CommandSignsMessagingProxy.newInstance(player, false);
proxy.sendMessage("Hi! Silent is turned off, so you can see this!");
proxy.setOp(true);
proxy.other_stuff();
然而,这个不起作用:
ConsoleCommandSender ccs = plugin.getServer().getConsoleSender();
CommandSender cs = (CommandSender)CommandSignsMessagingProxy.newInstance(ccs, false);
在运行时,此示例将生成以下内容:
java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender
答案 0 :(得分:3)
创建的代理类需要传递它想要实现的接口,
return Proxy.newProxyInstance(
sender.getClass().getClassLoader(),
sender.getClass().getInterfaces(),
new CommandSignsMessagingProxy(sender, receiver, silent));
失败似乎发生,因为可能无法从调用sender.getClass()。getInterfaces()方法返回CommandSender接口。因此,尝试通过调试来确定它是否正确通过。如果没有尝试手动将接口发送到该方法,看看它是否有效。