Search code examples
javagenericsobserver-pattern

Unsafe parameterized ArrayList cast after notify from Observable


I have a problem with the implementation of an update in the obersver pattern in JAVA. I send an ArrayList coming from my Queueing system to my Observer/s. The problem now is in the Observer where i receive the ArrayList as an Object. The next step would be a cast into an ArrayList but due to the runtime of Java I have no parameter information, which results in a unsafe cast. I mean i could notify my Observer with a whole generic class but i dont know if I am mistaken or it is "shooting with boulders on small birds". In result there is no error in the end cause I always notify this observer with ONE typ but the question is should I take the warning or is there a workaround.

            ArrayList<Message> messageList = sqsUtil.getMessagefromAnotherEntrypoint("myQueueName");
        if (messageList != null) {
            // notify Observers
            notifyObservers(messageList);

        }

And then the the Update where the unsafe cast happens

    @Override
public void update(Observable o, Object arg) {
    ArrayList<Message> aMessageList = (ArrayList<Message>)arg;

}

Nevertheless thanks for Help


Solution

  • JLS §5.1.9 talks about unchecked casts and when/why they happen. Long story short:

    • You don't check that arg is actually an ArrayList (i.e. arg instanceof ArrayList<?>).
    • There's no possible way to check if arg is an ArrayList that contains Message objects (at least not without using instanceof on each of the elements in the ArrayList). In other words, arg instanceof ArrayList<Message> doesn't compile.

    If you want to get rid of the warning (i.e. you know it won't throw an exception or you want it to if it does) then you can use @SuppressWarnings("unchecked"):

    @Override
    public void update(Observable o, Object arg) {
        @SuppressWarnings("unchecked")
        ArrayList<Message> aMessageList = (ArrayList<Message>) arg;
    }
    

    If you need to get only the messages and you don't want exceptions:

    @Override
    public void update(Observable o, Object arg) {
        ArrayList<Message> messages = new ArrayList<Message>();
        if (arg instanceof ArrayList<?>)
            for (Object o : (ArrayList<?>) arg)
                if (o instanceof Message)
                    messages.add((Message) o);
    
        // Do stuff with the messages list
    }
    

    This will get only the Message objects from arg if it's an ArrayList, otherwise it will be empty.