views:

128

answers:

2

Hi,

Suppose the following class

public class Message {
    // some code
}

And a Spring Validator implementation (no Spring knowledge required)

public class MessageValidator implements Validator {

    public boolean supports(Class clazz) {
        if(clazz.isAssignableFrom(Message.class))
            return true;
        else if(<ANSWER>)
            return true;

        return false;
    }

    public void validate(Object command, Errors errorArray) {
        if(command instanceof List)
            for(Message message: (List) command)
                validateMessage(message);
        else
            validateMessage((Message) command);
    }

    public void validateMessage(Message message, Errors errorArray) {
        // do validation Message object
    }

}

Notice supports method. What to put in <ANSWER> in order to support a List of Message - List<Message> ?

regards,

+3  A: 

Generic type argument information is (mostly) not retained at runtime so you don't have an easy way of accessing it. Basically, even though it says List<Message> it could still be a List<String>. There is no way of distinguishing the two without inspecting all the elements.

The best you can do is see if it implements List. Welcome to type erasure.

cletus
+1. However, it's not the end of the world in this particular case. You can always check the actual type of `List` element within `validate()` method and skip the validation if it's not `Message`.
ChssPly76
A: 

It's worth remembering the following distinction:

Objects don't have generic types. An actual List instance is just a straight ArrayList, or LinkedList, or whatever. The object itself does not have a generic type nor does it care about generics.

Variables on the other hand are declared generically. So you'd reference the object as a List<Foo>. This allows the compiler to enforce type-safety, but what you're really saying is that you want to treat the (untyped) List as a list of Foo, and you're asking the compiler to stop you from making calls that would insert Bars (for example).

Generics is just a compile time 'trick' built on top of the existing objects, so it makes no sense to check at runtime whether an object is an instance of List<Foo> - it's just an instance of List. In addition, runtime checking doesn't gain you anything since if it can't be checked at compile time, you get no benefit from the generics anyway.

Andrzej Doyle