java - 用 HashMap 替换 switch 语句

标签 java hashmap

我有一个接收包(字节数组)的套接字类。每个包都有一个整数来标识其类型。 switch 语句中的每个 case 如下所示:

switch(packet.getHeader().getID()) {
case PingRequest.ID:
    if(data.length != PingRequest.SIZE)
        return null;

    PingRequest pingRequest = new PingRequest(data); /* specific parsing of the byte array */
    pingRequest.setHeader(data); /* method of the abstract class */
    packet = pingRequest;
break;
case Error.ID:
    if(data.length != Error.SIZE)
        return null;

    Error error = new Error(data);
    error.setHeader(data);
    packet = error;

    break;
...

每个数据包都有不同的信息,这就是为什么每个数据包都有不同的构造函数(从字节数组data创建数据包成员)

由于每个案例看起来都有些相似(而且有很多),我认为我应该使用 HashMap 来优化它:

public static HashMap<Integer, Class<?>> _packetTypes = new HashMap<Integer, Class<?>>();
_packetTypes.put(PingRequest.ID, PingRequest.class);

我现在想要实现的是这样的:

Class<?> myClass = PacketAbstract._packetTypes.get(packet.getHeader().getID());

Class[] cArg = new Class[1];
cArg[0] = Byte.class;
Constructor<?> ct = myClass.getConstructor(cArg);

/* Doesn't make any sense from here on */
myClass specialPacket = ct.newInstance(data); 
specialPacket.setHeader(data);
packet = specialPacket;

所以基本的想法是创建一个 HashMap ,其中包含数据包 ID 和相应的数据包类,这将允许我创建专门的数据包。最后一个代码部分旨在替换我的 switch 语句。

问题:

我的解决这个问题的想法正确吗?如果没有请赐教。 如何实现到目前为止没有意义的代码的最后部分(如果这是正确的方法)?

编辑:数据包是抽象类Packet的对象,它由每个特殊数据包(如PingRequest)扩展

最佳答案

看来你的想法可行。我认为代码需要是这样的:

Class<? extends Packet> myClass = PacketAbstract._packetTypes.get(packet.getHeader().getID());

Constructor<Packet> ct = myClass.getConstructor(data.getClass());
Packet specialPacket = ct.newInstance(data);
specialPacket.setHeader(data);
packet = specialPacket;

但是,在我看来,使用反射通常是最后的手段。考虑研究其他模式,例如 Visitor Pattern这可能有助于解决此类问题。

另一种选择是将每个标识符的正确具体Class嵌入到枚举中,如下所示:

enum PacketID {
    private int id;
    private int size;
    private Class<? extends Packet> subClass;
    private PacketID(int id, int size, Class<? extends Packet> subClass) {
        this.id = id;
        this.size = size;
        this.subClass = subClass;
    }

    ERROR(  1, 100, Error.class),
    PINGREQ(2,  25, PingRequest.class);
}

这还允许您抽象出大小检查,这是我在第一个 HashMap 解决方案中没有看到的,并且可能完全跳过 HashMap

编辑:将参数更改为getConstructor(),因为您似乎使用字节数组而不仅仅是Byte。 编辑:使用枚举字段添加了第二个替代解决方案。

关于java - 用 HashMap 替换 switch 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16318836/

相关文章:

java - 在 MAP 中使用 Pojo 作为 key 无法找到 key Java 8

java - android:从List<HashMap>中将数据存储在Sqlite中

java - 找到Hashmap中的几个最大值

java - 将 ListenableScheduledFuture<Void> 转换为 ListenableFuture<SomethingElse>

Java调用方法

java - 我的拖放功能在 Android Studio 中不起作用

java - 我的(字符串).split ("=");不工作吗?

java - 如何从 spring boot kafka 项目连接到 aws MSK

java - 如何从非 JavaFX 线程调用 JavaFX Controller 并等待 GUI 更改完成(完成播放视频)?

java - HashMap get(Key) 函数在 Android AsyncTask 中不起作用