How i can check if a class is of a determinated type for example:
// PacketHandler.java
public interface PacketHandler<T> {
public void handlePacket(T packet);
}
// PacketReader.java
public void read() {
Packet packet = // Read some input
for(PacketHandler packetHandler : packetHandlers) {
if (packetHandler is the type of packet) { // here is the problem
packetHandler.handlePacket(packet);
}
}
}
public void registerHandler(PacketHandler<?> packetHandler) {
packetHandlers.add(packetHandler);
}
// Main
packetReader.registerHandler(new PacketHandler<RandomPacket>() {
public void handlePacket(RandomPacket packet) {
// I handle the packet
}
});
I know that this question maybe seems stupid; but how to solve this problem?
**Edit*****
Jon Skeet, so the class should be:
public class RandomClass implements PacketHandler {
public boolean handlePacket(Packet packet) {
if (packet instanceof PacketThatThisClassHandle) {
//handle with casting
return true;
} else {
return false;
}
}
}
Unfortunately Java generics use type erasure, meaning that at execution time, any particular PacketHandler<T>
is just PacketHandler
as far as the VM is concerned.
You may want to change your code to:
public interface PacketHandler {
// The parameter type can be Object if you really want
boolean tryHandlePacket(Packet packet);
}
... and make a PacketHandler
just return false
if it doesn't know how to handle a particular packet type.
Then you can just use:
for (PacketHandler handler : handlers) {
if (handler.tryHandlePacket(packet)) {
break;
}
}
(That's assuming you only want a single handler to actually handle any packet type.)
If you still want a generic interface, you'd either need a boolean handlesPacket(Packet)
method, or possibly a Class<T> getPacketType()
method. Either way it's still going to be a pain in terms of casting the packet to the right type...
If you have lots of packet handlers, you could potentially create an abstract base class:
public abstract class AbstractPacketHandler<T extends Packet>
implements PacketHandler {
private final Class<T> packetType;
protected AbstractPacketHandler(Class<T> packetType) {
this.packetType = packetType;
}
protected abstract void handlePacket(T packet);
public boolean tryHandlePacket(Packet packet) {
if (!packetType.isInstance(packet)) {
return false;
}
handlePacket(packetType.cast(packet));
return true;
}
}
Then you can write:
public class FooPacketHandler extends PacketHandler<Foo> {
public FooPacketHandler() {
super(Foo.class);
}
protected void handlePacket(Foo packet) {
...
}
}
See more on this question at Stackoverflow