Campbell Ritchie wrote:Please tell us what the book says; the original poster (=OP) might not have access to it.
Well, I am still too much a beginner but I will give my best in trying to explain -
because I think, that my exposure of a possible misunderstanding will help me
as well. So please correct me - I am very thankful if I can learn something
here.
As far as I understand it ...
The idea of wild
cards is described earlier in the book is really important
to understand this problem here as already described by Jesper. What the
book explains is the following:
The wild card is
NO type parameter, it is an
actual type parameter
(as Joshua Bloch would name it, or a specialized
type argument
(as Angelika Langer would name it): The specialization is called
wild
card type, what is probably not a good name for it (cause it is already
an "instantiation"). So as Jesper already said, the wildcard (?) stands for
the information: there exists an unknown type Tx for the given generic type
that makes it (the imagined parameterized generic type) a valid reference to the given
object instance.
e.g. having List<?> list (that is nothing than List<? extends Object>) says
There exists one Tx out of T, for that List<Tx> is a valid
parameterized type
to the provided object. But Tx is unknown to the compiler - it just knows, that the list
contains
only Tx type elements.
And now the first very important consequence: Each ? of the declarations generates
one
separate compiler capture. This is I think, what Jesper said, when telling
the compiler can't be sure that the "?" you used for Validator stands for
the same type as you used for the "?" in the Map
But the example above has another speciality. The documentation of the
newInstance() claims to return T. This is different to the java.lang.reflect.Array.newInstance()
method, that claims to return Object (no, not Object[] as one would assume) -
this because of primitive type arrays that need to be treated also in this case.
Both variants need to be casted to the actual parameterized type - and this is an
unchecked (and therefore evil (holy me ;) cast). The point here is
parameterized,
because at runtime this information is gone, so the given back instance is just
that one reflected by the class object - so in Petar's example, the Validator.
From the design point of view the book tells us, that in cast of unchecked casts, stay with
the rule of truth in advertising, that is:
The reified type of an array must be a subtype of the erasure of the static type
meaning, when using reflection whatever, make sure, that the function delivering the reference
to an object has the type of the instance. Inside this function you need to use unchecked casts,
what means *danger* but is necessary in case you want to develop e.g. a toArray method that
takes a List<Type> and gives back an array Type[].
Uff ... so .. and please now slaughter ... for sure I missed something or used somewhere a
wrong terminus technicus.
Cheers and have a nice evening,
Stephan