Java Class.cast()和Overload [英] Java Class.cast() and Overload

查看:218
本文介绍了Java Class.cast()和Overload的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为一个小服务器编码一个包侦听器。我是Java的新手,这是我第一次与网络混乱。整个想法它回收数据包,匹配数据包id与它的类,传递输入流到数据包的构造函数,所以它可以被构造,然后给它packetHander,对于每个数据包将有一个重叠的方法。为了使这个im使用一个数组,将数据包映射到每一个类的类,并使用一种称为decode的方法来构造数据包。问题是它的重载handlePacket它的行为不符合预期。让我们看一些代码。

I'm trying to code a packet listener for a little server. I'm very new to Java and this is the first time i mess around with networking. The whole idea it's recive the packet, match the packet id with it's class, pass the input stream to the constructor of the packet so it can be constructed and then give it to the packetHander, wich will have an overladed method for each packet. To achive this im using an array that maps the packets ids to the classes of each one, and using a method called decode to construct the packet. The problem it's the overloading of handlePacket it's not behaving as expected. Lets see some code.

我的包侦听器在一个线程中运行,并且run方法如下所示:

I've the packet listener running in a thread and the run method looks like this:

public void run() {
    try {
        int packet_id;
        while ((packet_id = istream.readInt()) != -1) {
            plugin.getServer().getConsoleSender().sendMessage("[Comm] Recived packet " + packet_id);
            Packet packet = decode(packet_id, istream);

            plugin.getServer().getConsoleSender().sendMessage("[Comm] Packet is " + Class.forName(packet.getClass().getName()));
                            plugin.getServer().getConsoleSender().sendMessage("[Comm] Class is " + Packet00ReqIdentify.class.cast(packet).getClass().getName());
            plugin.getServer().getConsoleSender().sendMessage("[Comm] Class is " + Class.forName(packet.getClass().getName()).getName());

            handlePacket(packet);
        }
    } catch (IOException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

decode和handlePacket方法如下: p>

The decode and handlePacket methods looks like this:

private void handlePacket(Packet00ReqIdentify packet) throws IOException {
    plugin.getServer().getConsoleSender().sendMessage("[Comm] Got it!");
}
private void handlePacket(Packet packet) {
    plugin.getServer().getConsoleSender().sendMessage("[Comm] Woops!");
}

private Packet decode(int packet_id, PacketInputStream istream) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IOException {
    Class<? extends Packet> packet_class = packets_ids.get(packet_id);
    try {
        Constructor<?> packet_constructor = packet_class.getConstructor(PacketInputStream.class);
        return Class.forName(packet_class.getName()).asSubclass(Packet.class).cast(packet_constructor.newInstance(istream));
    } catch (NoSuchMethodException e) {
        return  Class.forName(packet_class.getName()).asSubclass(Packet.class).cast(packet_class.newInstance());
    }
}

packets_ids这是一个包含对类的引用的数组

packets_ids it's an array that contains the reference to the class of each packet, indexed by theirs ids:

private static ArrayList<Class<? extends Packet>> packets_ids;

它以这种方式初始化:

private static void registerPacket(int id, Class<? extends Packet> oclass) {
    packets_ids.add(id, oclass);
}

static {
    packets_ids = new ArrayList<Class<? extends Packet>>();
    registerPacket(Packet00ReqIdentify.assigned_pid, Packet00ReqIdentify.class);
    registerPacket(Packet01Identify.assigned_pid, Packet01Identify.class);
    registerPacket(Packet02Heartbeat.assigned_pid, Packet02Heartbeat.class);
}

如果我执行这个测试,发送一个类型00的包,这:

If i execute this and test it sending a packet of type 00, i get this:

17:37:49 [INFO] [Comm] Connection established to localhost:11000
17:37:49 [INFO] [Comm] Recived packet 0
17:37:49 [INFO] [Comm] Packet is class com.gamerarg.commclient.protocol.Packet00ReqIdentify
17:37:49 [INFO] [Comm] Class is com.gamerarg.commclient.protocol.Packet00ReqIdentify
17:37:49 [INFO] [Comm] Class is com.gamerarg.commclient.protocol.Packet00ReqIdentify
17:37:49 [INFO] [Comm] Woops!

因此,这意味着packet00没有被handlePacket(Packet00ReqIdentify packet)。如果我在handlePacket调用中进行显式转换为packet,它会工作。所以问题是:

So it means the packet00 has not been cathed by "handlePacket(Packet00ReqIdentify packet)". If I make an explicit cast to "packet" in handlePacket call it works. So the questions are:


  • 为什么这不工作?当我打印类名称,我得到相同。

  • Why this it's not working? When i print the class names for both i get the same.

如何使它的工作?我一直在努力这个6或7小时,现在,阅读,谷歌,尝试和看到别人的代码。一个更简单的解决方案是使用数据包id切换,但我想要的东西更优雅。 Maybye我错了从基本的想法,所以这就是为什么我张贴的代码,我对建议和想法更多经验丰富的人的主题,包括材料的主题中的推荐。

How can I make it work? I been struggling with this for 6 or 7 hours for now, reading, googling, trying and seeing code from others. One simpler solution it's to make an switch using the packet id but i want something more elegant. Maybye i'm wrong from the base idea so that's why i posted the code, i'm open to suggestions and ideas of more experienced people in the subject, incluiding recomendations of material in the subject.

谢谢!

推荐答案

code>包子类,实现一个方法 public void handle()它执行你需要处理的数据包。

In each of your Packet subclasses, implement a method public void handle() which does what you need to handle the packet. Either


  • handle()的默认实现放在 code> Packet ,并使为抽象类

  • 包中声明 handle()并使一个界面。

  • Put a default implementation of handle() in Packet, or
  • Declare handle() as abstract in Packet, and make Packet an abstract class, or
  • Declare handle() in Packet and make Packet an interface.

然后替换

handlePacket(packet);

packet.handle();

这是多态操作。它将在运行时工作,检查引用的对象的类,并调用句柄的正确版本方法。

This is polymorphism in action. It will work at run time, checking the class of the object that packet references, and calling the right version of the handle method.

如果 handle()需要访问原始的 PacketListener ,然后将其声明为 public void handle(PacketListener listener),并将其称为 packet.handle(this);

If handle() needs access to the original PacketListener, then declare it as public void handle(PacketListener listener) and call it as packet.handle(this);

这篇关于Java Class.cast()和Overload的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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