Java方法重载混乱
在服务器代码中,我有一个Java方法重载混乱,java,inheritance,interface,overloading,Java,Inheritance,Interface,Overloading,在服务器代码中,我有一个ProtocolHandler类,它从套接字读取数据,找出它正在处理的数据包的类型,并将其发送给客户端。我尝试采用以下体系结构: public interface Packet { //... } public class ClientInformations implements Packet { //... } public class ProtocolHandler { //.... public void bytesReceiv
ProtocolHandler
类,它从套接字读取数据,找出它正在处理的数据包的类型,并将其发送给客户端。我尝试采用以下体系结构:
public interface Packet {
//...
}
public class ClientInformations implements Packet {
//...
}
public class ProtocolHandler {
//....
public void bytesReceived(byte[] bytes) {
//... Determine the type of the packet
Packet packet = determineTypeOfPacketAndRead(bytes);
// Here I already have the packet object built,
// like ClientInformations@1a1a1a1a[...]
client.packetReceived(packet);
}
//...
}
public class Client {
//...
public void packetReceived(Packet pkt) {
System.out.println("Unimplemented packet received.");
}
public void packetReceived(ClientInformations ci) {
}
//...
}
(我不知道如何用语言轻松地解释它)。问题是,我真的以为会调用packetReceived(ClientInformations)
,但事实并非如此。它调用更通用的packetReceived(Packet)
方法。我错了吗?那么,我怎么还能使用相同的体系结构呢
--编辑
现在我明白了为什么会这样。问题是,我还有其他包类,比如
移动
,同步
,繁殖
。我想通过向客户机
类添加一个新方法来简化添加新数据包的过程。那就没有别的办法了吗?我的意思是,一种在运行时自动分析数据包
对象类型并执行最具体的方法调用的方法?如果我理解正确,那么您传递的对象既是数据包
又是客户端信息
,因此,这两种方法都没有任何优先权
只要给另一个方法起一个不同的名字,你的问题就会解决。如果我理解正确的话,你传递的对象既是
数据包
又是客户端信息
,因此这两种方法都没有任何优先权
只需给另一种方法起一个不同的名字,您的问题就会得到解决。您必须按照以下步骤进行操作:
public void bytesReceived(byte[] bytes) {
//... Determine the type of the packet
packet = determineTypeOfPacketAndRead(bytes);
// Here I already have the packet object built,
// like ClientInformations@1a1a1a1a[...]
if (packet instanceof ClientInformations) {
ClientInformations ci = (ClientInformations)packet;
client.packetReceived(ci); // this way, it's clear which method you want to call
}
}
但是,我更喜欢Tim B的建议,即更改方法名称。我建议
clientinformationpacketreceived()
您必须按以下步骤执行:
public void bytesReceived(byte[] bytes) {
//... Determine the type of the packet
packet = determineTypeOfPacketAndRead(bytes);
// Here I already have the packet object built,
// like ClientInformations@1a1a1a1a[...]
if (packet instanceof ClientInformations) {
ClientInformations ci = (ClientInformations)packet;
client.packetReceived(ci); // this way, it's clear which method you want to call
}
}
但是,我更喜欢Tim B的建议,即更改方法名称。我建议
clientinformationpacketreceived()
我假设您有Packet-Packet=determineTYpeOfPacketAndRead(bytes)
,因为代码几乎没有其他编译方式
因此,即使对象类型是ClientInformations
(在运行时),引用类型也是Packet
(在编译时)
如Java语言规范第15章中所述,方法重载
在编译时选择最具体的方法;它的描述符确定在运行时实际执行的方法
更新:您的代码目前运行正常,因为您的代码中没有歧义,即使它的行为方式与您所希望的不同。但是,您将无法扩展此代码,因为它将导致问题,让我举例说明:
我先前的建议如下:
public class Client {
//...
public void unknownPacketReceived(Packet pkt) {
System.out.println("Unimplemented packet received.");
}
public void packetReceived(ClientInformations ci) {
}
//...
}
但是,这不能用作ClientInformations
对象。作为一个简单的数据包
对象/接口,它会产生以下编译错误:
incompatible types: Packet cannot be converted to ClientInformations
这是因为引用类型仍然只是数据包
,而您希望将其提升为客户端信息
但是,如果您将其称为:
client.receivedPacket((ClientInformations)packet)
在您的情况下,这不会造成任何伤害,因为在运行时,它们是相同类型的,因此在转换过程中不会丢失任何东西,这需要伴随一个instanceof
树,这就是为什么现在回到步骤0的原因
这个程序不仅可以运行,如果你想让它变得简单,我建议你改变你的设计。如果你正在处理一个遗留的应用程序,继续这个路径可能是一个选择,而且不能仅仅改变一些东西,但这并不容易。我假设你有
数据包=determineTYpeOfPacketAndRead(字节)
,因为几乎没有其他方法可以编译代码
因此,即使对象类型是ClientInformations
(在运行时),引用类型也是Packet
(在编译时)
如Java语言规范第15章中所述,方法重载
在编译时选择最具体的方法;它的描述符确定在运行时实际执行的方法
更新:您的代码目前运行正常,因为您的代码中没有歧义,即使它的行为方式与您所希望的不同。但是,您将无法扩展此代码,因为它将导致问题,让我举例说明:
我先前的建议如下:
public class Client {
//...
public void unknownPacketReceived(Packet pkt) {
System.out.println("Unimplemented packet received.");
}
public void packetReceived(ClientInformations ci) {
}
//...
}
但是,这不能用作ClientInformations
对象。作为一个简单的数据包
对象/接口,它会产生以下编译错误:
incompatible types: Packet cannot be converted to ClientInformations
这是因为引用类型仍然只是数据包
,而您希望将其提升为客户端信息
但是,如果您将其称为:
client.receivedPacket((ClientInformations)packet)
在您的情况下,这不会造成任何伤害,因为在运行时,它们是相同类型的,因此在转换过程中不会丢失任何东西,这需要伴随一个instanceof
树,这就是为什么现在回到步骤0的原因
这个程序不仅可以运行,如果你想让它变得简单,我建议你改变你的设计。如果你正在处理一个遗留的应用程序,继续这个路径可能是一个选择,而且不能仅仅改变一些东西,但这并不容易。你可以
类型转换
你的对象引用来调用packetReceived(ClientInformations)
而不是packetReceived(packetReceived)(packetReceived)(数据包)
您可以像这样调用client.packetReceived((ClientInformations)packet)您可以
typecast
您的对象引用调用packetReceived(ClientInformations)
而不是packetReceived(Packet)
您可以像这样调用client.packetReceived((ClientInformations)packet)代码>Java是一种单一的调度语言,所以诀窍在于学会利用