3

当我将动态代理类投射到我想要的对象时,我感到有些奇怪。在运行时,在某些情况下,我收到 ClassCastException。

为了更好地解释这一点,这里是我想要使用的类/接口的定义。任何(应该)不相关的扩展接口都被括号括起来。

public interface CommandSender (extends Permissible)
public interface ConsoleCommandSender extends CommandSender, (Conversable)
public interface Player extends (HumanEntity, Conversable), CommandSender, (OfflinePlayer, PluginMessageRecipient)

完整的 Javadocs 可以在这里找到: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
4

1 回答 1

4

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

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

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

于 2012-09-29T12:34:44.917 回答