I'm practicing socket communication with java, especially exchanging objects that the server and client know. if I only ever send one class type (Message), I can easily cast and rebuild it:
while (!socket.isClosed()) {
try {
Message message = (Message) objectInputStream.readObject();
System.out.println(data.getValue);
} catch (IOException | ClassNotFoundException ex) {
disconnected(ex);
}
}
Now I need to send different object types and I can't find the right way to implement it. someone suggests sending two messages: the first indicates the type and prepares the server for casting the second;
while (!socket.isClosed()) {
String type = null;
try {
if (type == null){
Message message = (Message) objectInputStream.readObject();
type = message.getType();
System.out.println(data.getValue);
} else {
//switch statement with possible types I can handle
//where I can have different casting
X message = (X) objectInputStream.readObject();
}
} catch (IOException | ClassNotFoundException ex) {
disconnected(ex);
}
}
In other cases I have seen the use of generics, but they cause quite a few problems because the type or cast is assumed as unsafe.
I would like a more versatile version that can dynamically convert objects coming from client and viceversa, something like this:
while (!socket.isClosed()) {
try {
Object data = objectInputStream.readObject();
//if object type is Message cast into a Message
//if object type is X cast into a X object
} catch (IOException | ClassNotFoundException ex) {
disconnected(ex);
}
}
Maybe I should go for something completely different, do you have any suggestions?
Object data = objectInputStream.readObject(); //if object type is Message cast into a Message //if object type is X cast into a X object
You're looking for instanceof
. Example:
Object data = objectInputStream.readObject();
if(data instanceof Message) {
Message m = (Message)data;
System.out.println("message type: "+m.type);
receivedMessage(m);
} else if(data instanceof X) {
X x = (X)data;
receivedX(m);
}
Since Java 14 there is also a shorthand syntax:
Object data = objectInputStream.readObject();
if(data instanceof Message m) { // <- note the name m
System.out.println("message type: "+m.type);
receivedMessage(m);
} else if(data instanceof X x) { // <- and here
receivedX(x);
}
If the type is totally unknown, you can also use getClass()
to get the type, which returns a Class
object and you can get information about it. (Beware that null.getClass()
will throw NPE)
Object data = objectInputStream.readObject();
if(data instanceof Message) {
receivedMessage((Message)data);
} else if(data == null) {
System.err.println("received null");
} else {
// don't know what it is, but it's not a Message
System.err.println("received unknown class "+data.getClass().getName());
}