generics question.

A

Amarnath B S

Could anyone help me by explaining the behaviour below?

----------code snippet start-----------

static <T> void some( T a[], Collection<T> c){
//nothing
}
.....
some(new Number[100], new ArrayList<Float>()); //compile time error
some(new Float[100], new ArrayList<Number>());//allowed
-----------code snippet end-------------

Why is the first method invocation not allowed? How does the compiler
compare the type dependencies?

thanks in advance,
Amarnath
 
T

Thomas Hawtin

Amarnath B S wrote (in a different order):
static <T> void some( T a[], Collection<T> c){
//nothing
}

Why is the first method invocation not allowed? How does the compiler
compare the type dependencies?
some(new Number[100], new ArrayList<Float>()); //compile time error

The second argument implies that T is Float. Number[] is not assignable
to Float[].
some(new Float[100], new ArrayList<Number>());//allowed

The second argument implies that T is Number. Float[] is assignable to
Number[].

Array types are quite eccentric. Best off sticking to collections.

Tom Hawtin
 
R

Roedy Green

static <T> void some( T a[], Collection<T> c){
//nothing
}
....
some(new Number[100], new ArrayList<Float>()); //compile time error
some(new Float[100], new ArrayList<Number>());//allowed

If machines were sentient, I think this get you a jail term for
compiler abuse.

I think the answer may become clear if in your call instead of relying
on type inference you used an explicit type in the invocation.

Another hint. Try reversing the order of the parms to some.
 
A

Amarnath

Roedy Green said:
static <T> void some( T a[], Collection<T> c){
//nothing
}
....
some(new Number[100], new ArrayList<Float>()); //compile time error
some(new Float[100], new ArrayList<Number>());//allowed

If machines were sentient, I think this get you a jail term for
compiler abuse.

I think the answer may become clear if in your call instead of relying
on type inference you used an explicit type in the invocation.

Another hint. Try reversing the order of the parms to some.

Compiler abuse!! I was just trying to understand it!! Anyway..,
Yes, I could have used explicit types, but I would like to understand the
compiler's behaviour here.

static <T> void some(Collection<T> c, T a[]){
}
.........
some(new ArrayList<Float>(), new Number[100]);

The above does not compile either.

-Amarnath
 
A

Amarnath

Thomas Hawtin said:
Amarnath B S wrote (in a different order):
static <T> void some( T a[], Collection<T> c){
//nothing
}

Why is the first method invocation not allowed? How does the compiler
compare the type dependencies?
some(new Number[100], new ArrayList<Float>()); //compile time error

The second argument implies that T is Float. Number[] is not assignable
to Float[].
some(new Float[100], new ArrayList<Number>());//allowed

The second argument implies that T is Number. Float[] is assignable to
Number[].

Array types are quite eccentric. Best off sticking to collections.

Tom Hawtin


If that is the case, then
static <T> void some(Collection<T> c, T a[]){
}
.........
some(new ArrayList<Float>(), new Number[100]);

should compile well. But it doesn't !!

-Amarnath
 
H

Hendrik Maryns

Amarnath schreef:
Amarnath B S wrote (in a different order):
static <T> void some( T a[], Collection<T> c){
//nothing
}

Why is the first method invocation not allowed? How does the compiler
compare the type dependencies?
some(new Number[100], new ArrayList<Float>()); //compile time error

The second argument implies that T is Float. Number[] is not assignable
to Float[].
some(new Float[100], new ArrayList<Number>());//allowed

The second argument implies that T is Number. Float[] is assignable to
Number[].

Array types are quite eccentric. Best off sticking to collections.

Tom Hawtin



If that is the case, then
static <T> void some(Collection<T> c, T a[]){
}
........
some(new ArrayList<Float>(), new Number[100]);

should compile well. But it doesn't !!

Read about arrays in the essay on generics. It is quite complex, and
quite a nuisance, for instance, you cannot do something like

List<State>[] stateList = new List<State>[15];

Only

List<?>[] stateList = new List<?>[15];

or

List<State>[] stateList = new List[15]; (*)

are allowed, the first making it impossible to add anything to the lists
and needing explicit casts when asking for one of the elements of the
list, the second generating an "unchecked" warning. The reason is that
generics are only in the compiler, and as arrays are also objects, they
can be assigned to Object variables, which leads to all kinds of problems.

See http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf, section 7.3,
but note that there is an error in there, specifically about the line (*).
Also read the section about fun with wildcards, which will probably
solve your problem above: you can write

static <T> void some(Collection<T> c, <? super T> a[]){
}
.........
some(new ArrayList<Float>(), new Number[100]);

H.

--
Hendrik Maryns

==================
www.lieverleven.be
http://aouw.org
 
B

Brendan Guild

Amarnath wrote in news:1133255627.68550@sj-nntpcache-5:
static <T> void some(Collection<T> c, T a[]){
}
........
some(new ArrayList<Float>(), new Number[100]);

The above does not compile either.

Would you want it to compile? If I was writing a function some
(Collection<T> c, T a[]), I would sure want to be able to put the
elements of 'a' into 'c'. But how can I do that if 'a' is an array of
all kinds of Numbers and 'c' can only hold Floats?

If you make it explicit that 'c' and 'a' hold the same kind of things,
then why would you want to start putting something else in there?

Of course, arrays are a different thing than collections; arrays are
more powerful and even a little dangerous. Float[] is a subtype of
Number[], so you can pass in a Float[] where a Number[] is expected
without complaint and everything works just right. That's why some(new
ArrayList<Number>(), new Float[100]) would work, because it is expecting
a Number[] but accepts a Float[]. If you try to put something from 'c'
into 'a' that isn't actually a Float, you'll get a runtime exception.

Some people seem to think that arrays are worse than collections because
of this, if I understand their posts correctly, but I probably don't
because I don't see a problem with it. I wish collections could be as
powerful as arrays! Then I could do away with using real arrays all
together.
 
T

Thomas Hawtin

Amarnath said:
Amarnath B S wrote (in a different order):
static <T> void some( T a[], Collection<T> c){
//nothing
}

Why is the first method invocation not allowed? How does the compiler
compare the type dependencies?
some(new Number[100], new ArrayList<Float>()); //compile time error

The second argument implies that T is Float. Number[] is not assignable
to Float[].
some(new Float[100], new ArrayList<Number>());//allowed

The second argument implies that T is Number. Float[] is assignable to
Number[].
If that is the case, then
static <T> void some(Collection<T> c, T a[]){
}
........
some(new ArrayList<Float>(), new Number[100]);

should compile well. But it doesn't !!

I really don't follow your logic there at all. Applying my argument as
above to this example:

The argument "new ArrayList<Float>()", of type ArrayList<Float>, implies
that T is Float. The argument "new Number[100]", of type Number[], is
not assignable to Float[].

Tom Hawtin
 
O

Oliver Wong

Brendan Guild said:
Of course, arrays are a different thing than collections; arrays are
more powerful and even a little dangerous. Float[] is a subtype of
Number[], so you can pass in a Float[] where a Number[] is expected
without complaint and everything works just right. That's why some(new
ArrayList<Number>(), new Float[100]) would work, because it is expecting
a Number[] but accepts a Float[]. If you try to put something from 'c'
into 'a' that isn't actually a Float, you'll get a runtime exception.

Some people seem to think that arrays are worse than collections because
of this, if I understand their posts correctly, but I probably don't
because I don't see a problem with it. I wish collections could be as
powerful as arrays! Then I could do away with using real arrays all
together.

Under your definition of "more powerful", I think Collections are
actually more powerful than arrays. If you want to say "I want a collection
of Numbers, but I'm willing to take a collection of Floats, 'cause Floats
are Numbers, and I'm just planning on pulling stuff out of the collection."
then you would write, for example "ArrayList<? extends Number>". So with
this syntax alone, Collections are of the same power as arrays. But you have
more control over Collections.

You can also say "I want a collection. I don't care what kind of
collection it is, but I wanna be able to put Numbers in it, so if you give
me a collection of Objects, that's okay too." The syntax is "ArrayList<?
super Number>".

Finally you can say "I want a collection of Numbers and nothing but
numbers. Collection of Floats is no good, because I may want to insert
Numbers, and collection of Objects is no good, because I want to be sure
that when I take an element out, it's a Number". The syntax for that is
"ArrayList<Number>".

- Oliver
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

generics puzzle 57
can this be done with generics? 32
newInstance, generics, and "unchecked or unsafe operations" 6
Generics 12
Help on java generics 18
JDK5 Generics 6
Generics annoyance 18
Generics Question 4

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top