Search code examples
javasocketsdynamiccastingstream

how to cast various objects from an objectInputStream


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?


Solution

  • 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());
    }