加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Java Class.cast()和重载

发布时间:2020-12-15 04:16:55 所属栏目:Java 来源:网络整理
导读:我正在尝试为一个小服务器编写数据包监听器.我是 Java的新手,这是我第一次搞乱网络.整个想法是重新接收数据包,将数据包id与它的类匹配,将输入流传递给数据包的构造函数,以便可以构造它然后将其提供给packetHander,它将为每个数据包提供重叠方法.要使用将数据
我正在尝试为一个小服务器编写数据包监听器.我是 Java的新手,这是我第一次搞乱网络.整个想法是重新接收数据包,将数据包id与它的类匹配,将输入流传递给数据包的构造函数,以便可以构造它然后将其提供给packetHander,它将为每个数据包提供重叠方法.要使用将数据包ID映射到每个类的数组,并使用一个名为decode的方法来构造数据包,来实现这个im.问题是handlePacket的重载它没有按预期运行.让我们看一些代码.

我在一个线程中运行数据包监听器,run方法如下所示:

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方法如下所示:

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它是一个数组,包含对每个数据包类的引用,由他们的id索引:

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的数据包,我得到这个:

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”进行显式转换,则它可以工作.所以问题是:

>为什么这不起作用?当我打印两个类名时,我得到相同的.
>我怎样才能让它发挥作用?我现在一直在努力工作6到7个小时,阅读,谷歌搜索,尝试和查看其他人的代码.一个更简单的解决方案是使用数据包ID进行切换,但我想要更优雅的东西. Maybye我的基本想法是错的,这就是我发布代码的原因,我对这个主题中更有经验的人的建议和想法持开放态度,包括对主题材料的推荐.

谢谢!

解决方法

在每个Packet子类中,实现一个方法public void handle(),它执行处理数据包所需的操作.或

>在Packet中放置handle()的默认实现,或
>在Packet中将handle()声明为抽象,并使Packet成为抽象类,或
>在Packet中声明handle()并使Packet成为接口.

然后更换

handlePacket(packet);

packet.handle();

这是行动中的多态性.它将在运行时工作,检查数据包引用的对象的类,并调用正确的handle方法版本.

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读