implicit <? super T> when an array is a parameter in a generic method  
Author Message
Murat Tasan





PostPosted: 2004-12-14 5:30:00 Top

java-programmer, implicit <? super T> when an array is a parameter in a generic method i'm making some adjustments to previous code to utilize generics in java
1.5 or 5.0 or whatever it is called. something seems inconsistent,
though:
let us say i have a method that operates on two collections:

public <T> void testMethod(Collection<T> c1, Collection<T> c2){...}

if i call this method with the following line, a compile-time error
occurs:
testMethod(new HashSet<Integer>(), new HashSet<Number>());

and rightly so. in this case T != T (i.e. Integer != Number).

the method would have to be rewritten to:

public <T> void testMethod(Collection<T> c1, Collection<? super T>
c2){...}
and this indeed works. this is fine and quite logical.

now the problem. let us assume i have a method that copies elements
from an array into a collection:
public <T> void testMethod(T[] a, Collection<T> c){...}

suddenly i'm allowed to call this method with T != T, as in:

testMethod(new Integer[100], new HashSet<Number>());

the official word from sun is: "it will generally infer the most
specific type argument that will make the call type-correct." apparently this
line is only in reference to arrays (although they don't mention that).
so when this "inferring" occurs, is there basically a re-writing going
on the background that equates to changing the function to:
public <T> void testMethod(T[] a, Collection<? super T> c){...}

?

i guess the true root of the question is, which of the parameters (and
indeed there may be many) will be going through the inferring process?
there must be at least one "baseline" argument type parameter in calls
like these that remains fixed (i.e. cannot go through an inferring
process), because otherwise every type argument could just be inferred to be
Object, making all calls legit and ruining the advantage of generics.
wow, that may have been a bit confusing, but if anyone would point me to
a general good source on java's version of generics (not sun's
documents, as i've already tried to read those and they don't clear up this
confusion at all), it would be greatly appreciated.
thanks,

murat




 
hilz





PostPosted: 2004-12-14 5:44:00 Top

java-programmer >> implicit <? super T> when an array is a parameter in a generic method This is a fairly advanced question, and you might get better answers if you
post it to c.l.j.programmer rather than c.l.j.help (which is mostly for
beginners)



 
Chris Smith





PostPosted: 2004-12-14 6:30:00 Top

java-programmer >> implicit <? super T> when an array is a parameter in a generic method Murat Tasan <email***@***.com> wrote:
> i guess the true root of the question is, which of the parameters (and
> indeed there may be many) will be going through the inferring process?

The inferral you saw mention of is about the identity of the mystery
type, T. The types of the formal and actual parameters are used as
clues to deduce the value of T. See below.

The type inferrence from generics doesn't apply only to arrays.
However, there is an age-old property of arrays that makes a difference
in your example.

When you call a generic method, the compiler is tasked with discovering
the exact value of the type parameter. It does this by examining each
formal parameter and the corresponding type of its actual parameter. In
your first case, there was no such type parameter which will cause the
arguments to work, so an error message results. Specifically, the
signature and call are:

public <T> void testMethod(Collection<T> c1, Collection<T> c2)

testMethod(new HashSet<Integer>(), new HashSet<Number>());

Now, if T were Integer (or anything more specific), then the second
parameter wouldn't work. If T were Number (or anything more general)
then the first parameter wouldn't work. So you get an error message.

However, in your second example, there is a way out. You have:

public <T> void testMethod(T[] a, Collection<T> c)

testMethod(new Integer[100], new HashSet<Number>());

Here, if T = Number, everything work fine. The resulting method
signature is:

public void testMethod(Number[] a, Collection<Number> c)

This may look inappropriate to you, but arrays follow the rather suspect
rule of parallel inheritance; so if Integer extends Number, that implies
that Integer[] extends Number[]. Hence, your method call, which passes
Integer[] for a formal parameter of type Number[], is no more impossible
than passing String to a method that expects Object.

(Note that T must be Number here; anything more specific, and both
parameters fail type checks, but anything more general causes at least
the second parameter to fail type checks.)

It is perfectly appropriate. You may disagree with this rule about
arrays and inheritance. In fact, if you do, join the club. I'm sure
most everyone at Sun is regretting the day they devised such a thing.
However, it's still there and enshrined in the JLS, and has been since
Java first existed. On the other hand, generic collections don't obey
any such rule.

> so when this "inferring" occurs, is there basically a re-writing going
> on the background that equates to changing the function to:
> public <T> void testMethod(T[] a, Collection<? super T> c){...}
>
> ?

No, that's not what's happening. Hopefully, what I've written above is
clear enough to explain the phenomenon.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
 
Chris Smith





PostPosted: 2004-12-14 6:33:00 Top

java-programmer >> implicit <? super T> when an array is a parameter in a generic method hilz <email***@***.com> wrote:
> This is a fairly advanced question, and you might get better answers if you
> post it to c.l.j.programmer rather than c.l.j.help (which is mostly for
> beginners)

This is becoming a problem. We now know your definition of "beginner",
but I suspect if this person posted in .programmer, Andrew would be
sending him/her back here. Shall we play ping-pong with people as
balls, or just answer people's questions? There are very few people who
don't read both groups, anyway.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
 
hilz





PostPosted: 2004-12-15 6:39:00 Top

java-programmer >> implicit <? super T> when an array is a parameter in a generic method
> This is becoming a problem. We now know your definition of "beginner",
> but I suspect if this person posted in .programmer, Andrew would be
> sending him/her back here. Shall we play ping-pong with people as
> balls, or just answer people's questions? There are very few people who
> don't read both groups, anyway.

Chris:
I did not mean in any way to insult, offend or attack the OP. I just said
that i thought he/she might get better response from c.l.j.programmer since
more advanced users tend to read that group.
i did not know that most people read both, and still, i am sure there are
people who read only c.l.j.programmer and are more capable of answering that
question.

If i knew the answer, i would have just answered it without referring the OP
to any another group since that is not my specialty!
cheers.
hilz