Casting Proxies - 获取ClassCastException

时间:2012-09-29 12:21:19

标签: java casting proxy-classes

当我将动态代理类转换为我想要的对象时,我会有些奇怪。在运行时,在某些条件下,我收到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

1 个答案:

答案 0 :(得分:3)

创建的代理类需要传递它想要实现的接口,

return Proxy.newProxyInstance(
                sender.getClass().getClassLoader(),
                sender.getClass().getInterfaces(),
                new CommandSignsMessagingProxy(sender, receiver, silent));

失败似乎发生,因为可能无法从调用sender.getClass()。getInterfaces()方法返回CommandSender接口。因此,尝试通过调试来确定它是否正确通过。如果没有尝试手动将接口发送到该方法,看看它是否有效。