Reputation: 6521
I am trying to understand, why compiler rejects / accepts the following arguments.
I assumed, that both arguments would be accepted, because both Sets contain nothing, but children of Serializable.
And being a child of Serializable - is the only thing, which is enforced by method signature D extends Serializable - right?
Why is the Set serializables1 of type D extends Serializable accepted?
Why is the Set serializables2 of type ? extends Serializable rejected?
Why is D extends Serializable and ? extends Serializable is not the same here?
public class GenTest<D extends Serializable> {
Set<D> serializables1;
Set<? extends Serializable> serializables2;
public static void main(String[] args) {
GenTest<Serializable> g = null;
g.accept(g.serializables1); // OK - WHY?
g.accept(g.serializables2); // NOT OK - WHY?
}
void accept(Set<D> serializables) {}
}
Upvotes: 1
Views: 118
Reputation: 62864
According to the signature, the .accept()
method uses the class-scoped D
type-parameter:
void accept(Set<D> serializables) {}
When instantiating GenTest
as GenTest<Serializable> g = null;
means that D
will be replaced at Runtime with Serializable
.
Now, what does Set<? extends Serializable> serializables2
mean?
It means that serializables2
can be assigned with a Set
of unknown subclasses of Serializable
. The compiler has no evidence that this unknown subclass will match the substitute of D
at Runtime, and hence rejects to allow the code to compile.
Let's say you have these two types:
class A implements Serializable { }
class B implements Serializable { }
Set<? extends Serializable> serializables2
means that serializables2
can either be assigned with Set<A>
or assigned with Set<B>
at Runtime. Let's suppose it is assigned with Set<B>
.
Now, if your g.serializables
contain only objects of type A
(which is possible, because the D
is replaced by Serializable
), this means that at Runtime you'll get a ClassCastException
, when trying to pass a Set<B>
to a method should be provided with a Set<A>
.
More info:
Upvotes: 3
Reputation: 838
serializables1 contains a "Set of D", accept() accepts a "Set of D". The type hierarchy of D is not important. serializables2 can be any Serializable. Casting down to D is not possible.
Upvotes: 0
Reputation: 18123
Set<? extends Serializable>
says exactly that the set contains a type which inherits Serializable
but is not known so you have a kind of backwards compatibility to the pre-generics days without the possibility of changing the set - and your compiler has no knowledge whether ?
complies to D
in your example so he prohibits the given usage.
Upvotes: 0
Reputation: 8200
When using ? extends Serializable
it can be an object of any class that implements Serializable
and not just D
, therefore it does not work.
Upvotes: 0