Java 用HashMap替换switch语句
我有一个套接字类,它接收包(字节数组)。每个包都有一个整数以标识其类型。switch语句中的每种情况如下所示:Java 用HashMap替换switch语句,java,hashmap,Java,Hashmap,我有一个套接字类,它接收包(字节数组)。每个包都有一个整数以标识其类型。switch语句中的每种情况如下所示: switch(packet.getHeader().getID()) { case PingRequest.ID: if(data.length != PingRequest.SIZE) return null; PingRequest pingRequest = new PingRequest(data); /* specific parsing o
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;
...
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;
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;
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对其进行优化:
public static HashMap<Integer, Class<?>> _packetTypes = new HashMap<Integer, Class<?>>();
_packetTypes.put(PingRequest.ID, PingRequest.class);
公共静态HashMap>();
_packetTypes.put(PingRequest.ID,PingRequest.class);
我现在想要实现的是这样的目标:
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;
...
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;
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;
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);
}
Class myClass=PacketAbstract.\u packetTypes.get(packet.getHeader().getID());
类别[]cArg=新类别[1];
cArg[0]=Byte.class;
构造函数ct=myClass.getConstructor(cArg);
/*从现在开始没有任何意义*/
myClass specialPacket=ct.newInstance(数据);
specialPackage.setHeader(数据);
数据包=特殊数据包;
因此,基本的想法是创建一个hashmap,其中包含数据包id和相应的数据包类,允许我创建专门的数据包。最后一段代码是用来替换我的switch语句的
问题:
我的解决方法正确吗?如果没有,请告诉我。
我如何实现我的代码的最后一部分,这到目前为止还没有意义(如果这是正确的方法)
编辑:packet是抽象类packet
的一个对象,它被每个特殊的包扩展,比如PingRequest
,看起来你的想法是可行的。我认为代码应该是这样的:
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;
...
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;
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;
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
。
编辑:添加了使用枚举字段的第二个备选解决方案。classmyclass=PacketAbstract.\u packetTypes.get(packet.getHeader().getID());
Class<?> myClass = PacketAbstract._packetTypes.get(packet.getHeader().getID());
Class[] cArg = new Class[1];
cArg[0] = byte[].class; // not Byte.class
Constructor<?> ct = myClass.getConstructor(cArg);
Object specialPacket = ct.newInstance(data);
Method mt = myClass.getMethod("setHeader", byte[].class)
mt.invoke(specialPacket, data);
packet = specialPacket;
类别[]cArg=新类别[1];
cArg[0]=字节[]。类;//不是Byte.class
构造函数ct=myClass.getConstructor(cArg);
objectspecialpacket=ct.newInstance(数据);
方法mt=myClass.getMethod(“setHeader”,字节[].class)
mt.invoke(特殊包、数据);
数据包=特殊数据包;
您是否可以使用工厂模式(例如在)
比如:
interface Packet {
void parse(Datatype data);
void setHeaders (Datatype data);
}
class PingPacket implements Packet {
void parse (Datatype data) {
....
....
}
void setHeaders(Datatype data) {
...
...
}
}
class ErrorPacket implements Packet {
void parse (Datatype data) {
.....
.....
}
void setHeaders(Datatype data) {
...
...
}
}
class PacketFactory {
Packet getInstance(int packetId) {
if (packetId == Ping_ID) {
...
...
return new PingPacket();
} else if (packetId == ERROR_ID) {
...
...
return new ErrorPacket();
}
}
}
Class.newInstance()
可以工作,但必须更改代码才能为这些子类使用默认构造函数。@RobI oops。。。这是个错误。修正。然后我必须为每个ID编写数百个if(packetId==Ping_ID)
,一个if语句,这与使用switch语句相同。是的,您必须编写许多if语句,但最终避免了switch的每个case语句中重复的代码块,或者您可以修改PacketFactory getInstance(int packetId),这样它就可以从HashMap中找到子类名称(必须用key作为packetId,value作为classname来构造),然后使用stackoverflow问题中指定的答案从string中实例化类