铸造代理 - 获取ClassCastException [英] Casting Proxies - Getting ClassCastException

查看:124
本文介绍了铸造代理 - 获取ClassCastException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我将一个动态代理类转换为我想要的对象时,我遇到了一些奇怪。在运行时,在某些条件下,我收到一个ClassCastException。

I'm getting some weirdness when I'm casting a Dynamic Proxy Class to the object I want it to be. At runtime, under certain conditions, I receive a ClassCastException.

为了更好地解释这一点,这里是我想使用的类/接口的定义。

In order to explain this better, here are the definitions for the classes/interfaces I want to use. Brackets have been put around any extended interfaces that (should be) irrelevant.

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

Full Javadocs can be found here: http://jd.bukkit.org/apidocs/org/bukkit/command/CommandSender.html

现在,这里是我的代理类的代码:

Now, here is the code for my proxy class:

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);

在运行时,此示例将生成以下内容:

At run time, this example would produce the following:

java.lang.ClassCastException: $Proxy18 cannot be cast to org.bukkit.command.CommandSender


推荐答案

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

The created proxy class need to pass the interfaces it suppose to implement,

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

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

failure seems to happen because CommandSender interface may not be returned from the call sender.getClass().getInterfaces() method. So try to see if it properly passes by debugging. If not try sending the interface manually to the method and see if it works.

这篇关于铸造代理 - 获取ClassCastException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆