Java generics mystery

Here is a puzzle for Generics gurus.

Can somebody explain why

Set<Address> addresses = new HashSet<Address>();
Set<?> things = addresses;

compiles but

Set<ConstraintValidator<Address>> validatedAddresses = 
    new HashSet<ConstraintValidator<Address>>();
Set<ConstraintValidator<?>> validatedThings =
    validatedAddresses;

does not compile?

More specifically, the assignment on the second line breaks.

3 comments to Java generics mystery

  • Vivien Barousse

    That's because ConstraintValidator<?> is not equals to ConstraintValidator<Address>. Parametrized types are expected to be strictly equals.

    You can solve this issue by using generic wildcards :
    Set<? extends ConstraintValidator<?>> validatedThings = validatedAddresses;

    This is discussed more in the Java language specification, §4.5.

  • Emmanuel Bernard

    Yes but the surprising thing is that I can do
    ConstraintValidator<Address> a;
    ConstraintValidator<?> thing = a;

    But as soon as I use a Set<ConstraintValidator<Address>> which is a container of ConstraintValidator<Address>, I cannot assign it to Set<ConstraintValidator<?>>

    Set<? extends ConstraintValidator<?>> works but it seems to imply that ? extends ConstraintValidator<?> contains ConstraintValidator<Address> while a plain ConstraintValidator<?> does not (which contradicts my first statement).

  • Josh McDonald

    Set<SubClass> extends Set<?>, but it doesn't extend Set<BaseClass>. Annoying, but the way of things.

    Replace SubClass with Set<OtherClass>, and BaseClass with Set<?>. Even though Set<OtherClass> extends Set<?>, Set<Set<OtherClass>> will still not extend Set<Set<?>>. Given the first situation, I think it would be strange to expect otherwise.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>