Java generic issue in array

J

jacksu

I could create:

ArrayList<Node> myarr = new ArrayList<Node>();

but can't

ArrayList<Node> myarr[] = new ArrayList<Node>[n];
I got error "Cannot create a generic array of ArrayList<Node>

any suggsetion?

Thanks.
 
N

nkalagarla

generic array creation is not allowed.Try following work-around.

ArrayList<Node>[] myarr = (ArrayList<Node>[])
Array.newInstance(ArrayList.class,n);
 
L

Luc The Perverse

generic array creation is not allowed.Try following work-around.

ArrayList<Node>[] myarr = (ArrayList<Node>[])
Array.newInstance(ArrayList.class,n);

Eh?

What in the world is that?

I think the more common way is (at least what I have seen):

Where n is some integer:

ArrayList<Node>[] myarr = new ArrayList[n];
for(int i=0;i<n;i++)
myarr = new ArrayList<Node>(); //initialize each individually
 
N

nkalagarla

Well, with my approach you won't get any warning. With yours, you will
see one warning and to suppress it you have to specify
@SuppressWarnings("unchecked") annotation.

:)
 
C

Chris Smith

Well, with my approach you won't get any warning. With yours, you will
see one warning and to suppress it you have to specify
@SuppressWarnings("unchecked") annotation.

:)

Didn't you mean that the other way around? Casting from Object (the
return type of Array.newInstance) to ArrayList<Node>[] ought to result
in an unchecked cast warning. Nothing in Luc's response seemed to
require this warning.

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

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

Mike Schilling

Chris Smith said:
Well, with my approach you won't get any warning. With yours, you will
see one warning and to suppress it you have to specify
@SuppressWarnings("unchecked") annotation.

:)

Didn't you mean that the other way around? Casting from Object (the
return type of Array.newInstance) to ArrayList<Node>[] ought to result
in an unchecked cast warning. Nothing in Luc's response seemed to
require this warning.


Luc's

ArrayList<Node>[] myarr = new ArrayList[n];

causes a warning:

Warnings.java:8: warning: [unchecked] unchecked conversion
found : java.util.ArrayList[]
required: java.util.ArrayList<java.lang.String>[]
ArrayList<String>[] myarr = new ArrayList[12];
 
C

Chris Smith

Mike Schilling said:
ArrayList<Node>[] myarr = new ArrayList[n];

Yep, you're right. I picked up that confusion from an early version of
the Eclipse generics compiler. It appears that nkalagarla also did the
same, since the warning from his/her post was apparently missing in
Eclipse up to 3.2M6, and fixed there. With the current 3.2 milestone,
both options correctly give warnings.

That'll teach me to read the spec before replying with something I don't
understand. :)

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

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

Tony Morris

jacksu said:
I could create:

ArrayList<Node> myarr = new ArrayList<Node>();

but can't

ArrayList<Node> myarr[] = new ArrayList<Node>[n];
I got error "Cannot create a generic array of ArrayList<Node>

any suggsetion?

Thanks.

You cannot do that.
Ponder the thought: you cannot write a 1.5 java.util.ArrayList
implementation without generating a compile-time warning. Some say generics
are broken, others (fewer) say arrays are broken - it's all guff on top of a
flawed premise though.
 
T

Thomas Hawtin

jacksu said:
I could create:

ArrayList<Node> myarr = new ArrayList<Node>();

but can't

ArrayList<Node> myarr[] = new ArrayList<Node>[n];
I got error "Cannot create a generic array of ArrayList<Node>

Don't use arrays of references...

Instead use:

List<List<Node>> nodeLists = new ArrayList<List<node>>();

IIRC, the Joshua Bloch's Effective Java Reloaded session at JavaONE
covered that sort of thing. </appeal-to-authority>

Alternatively add a class for the concept of the particular use of a
List of Nodes:

class NodeString {
private final List<Node> nodes;
}
....
List<NodeString> nodeStrings = new ArrayList<NodeString>();

Tom Hawtin
 
M

Mike Schilling

Ponder the thought: you cannot write a 1.5 java.util.ArrayList
implementation without generating a compile-time warning. Some say
generics are broken, others (fewer) say arrays are broken - it's all guff
on top of a flawed premise though.

Nitpick: you can do it in later versions of 1.5 by using an annotation that
specifically turns that warning off. Only a slight improvement, I agree.
 
M

Mike Schilling

Chris Smith said:
Mike Schilling said:
ArrayList<Node>[] myarr = new ArrayList[n];

Yep, you're right. I picked up that confusion from an early version of
the Eclipse generics compiler. It appears that nkalagarla also did the
same, since the warning from his/her post was apparently missing in
Eclipse up to 3.2M6, and fixed there. With the current 3.2 milestone,
both options correctly give warnings.

That'll teach me to read the spec before replying with something I don't
understand. :)

If you're implying that you'd understand it after you read the spec, it must
be a better-written spec than the ones I've seen.
 
C

Chris Smith

Mike Schilling said:
If you're implying that you'd understand it after you read the spec, it must
be a better-written spec than the ones I've seen.

Well, no, but understanding specs is not impossible -- just an acquired
skill. I would have said "yes" until the third edition came out.
Generics, though, complicate the specification even more than the
language.

Here's what I'm seeing here doesn't lead to the conclusion I expected,
though. Perhaps someone can clarify. The expression in question was:

ArrayList<Node>[] arr = new ArrayList[n];

Eclipse and javac both compile this but give a warning about unchecked
conversion.

5.2 (Assignment Conversion) says that we have two options for the
assignment conversion. We should apply (among other irrelevant things)
widening reference conversion to convert the type ArrayList[] to
ArrayList<Node>[] first. If that's not possible, we should apply
unchecked conversion to do so.

5.1.5 (Widening Reference Conversions) says that widening primitive
conversion is only possible if the type ArrayList[] is a subtype of
ArrayList<Node>[].

4.10.3 (Subtyping among Array Types) says that ArrayList[] is a subtype
of ArrayList<Node>[] if and only if ArrayList is a subtype of
ArrayList[].

4.10.2 (Subtyping among Class and Interface Types) says that
ArrayList<Node> is a subtype of ArrayList, but NOT vice versa. So we've
failed.

Back to 5.2 (Assignment Conversion), the next option is to apply
unchecked conversion from ArrayList[] to ArrayList<Node>[]. This only
applies if ArrayList[] is a raw type.

4.8 (Raw Types) makes ArrayList[] NOT a raw type, even though its
component type is a raw type. Therefore we can't apply unchecked
conversion.

So it seems that the code above should actually fail to compile. Yet it
does compile. To make that correct, it would seem that it would be
necessary to expand the definition of unchecked conversion in 5.1.9 to
include the rule that if an unchecked conversion exists from T to S,
then an unchecked conversion exists from T[] to S[], and then to update
text in sections like 5.2 to remove the requirement (which is
unnecessary anyway) that unchecked conversion is only applied to raw
types.

Anyone disagree? What am I missing?

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

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

Mike Schilling

Chris Smith said:
Well, no, but understanding specs is not impossible -- just an acquired
skill. I would have said "yes" until the third edition came out.
Generics, though, complicate the specification even more than the
language.

Exactly my point. The second edition has some complications (the worst I
can recall offhand being the rules for resolving method overloads), but they
can be mastered with a bit of study. This remains true for the 1.5
additions to the language other than generics. Geenrics are explained in a
way that does not answer a large number of questions, which then have to be
resolved by trying things and wondering if javac implements the spec
correctly.
 
D

Dale King

Chris said:
Mike Schilling said:
If you're implying that you'd understand it after you read the spec, it must
be a better-written spec than the ones I've seen.

Well, no, but understanding specs is not impossible -- just an acquired
skill. I would have said "yes" until the third edition came out.
Generics, though, complicate the specification even more than the
language.

Here's what I'm seeing here doesn't lead to the conclusion I expected,
though. Perhaps someone can clarify. The expression in question was:

ArrayList<Node>[] arr = new ArrayList[n];

Eclipse and javac both compile this but give a warning about unchecked
conversion.

5.2 (Assignment Conversion) says that we have two options for the
assignment conversion. We should apply (among other irrelevant things)
widening reference conversion to convert the type ArrayList[] to
ArrayList<Node>[] first. If that's not possible, we should apply
unchecked conversion to do so.

5.1.5 (Widening Reference Conversions) says that widening primitive
conversion is only possible if the type ArrayList[] is a subtype of
ArrayList<Node>[].

4.10.3 (Subtyping among Array Types) says that ArrayList[] is a subtype
of ArrayList<Node>[] if and only if ArrayList is a subtype of
ArrayList[].

4.10.2 (Subtyping among Class and Interface Types) says that
ArrayList<Node> is a subtype of ArrayList, but NOT vice versa. So we've
failed.

Back to 5.2 (Assignment Conversion), the next option is to apply
unchecked conversion from ArrayList[] to ArrayList<Node>[]. This only
applies if ArrayList[] is a raw type.

4.8 (Raw Types) makes ArrayList[] NOT a raw type, even though its
component type is a raw type. Therefore we can't apply unchecked
conversion.

So it seems that the code above should actually fail to compile. Yet it
does compile. To make that correct, it would seem that it would be
necessary to expand the definition of unchecked conversion in 5.1.9 to
include the rule that if an unchecked conversion exists from T to S,
then an unchecked conversion exists from T[] to S[], and then to update
text in sections like 5.2 to remove the requirement (which is
unnecessary anyway) that unchecked conversion is only applied to raw
types.

I think the problem is that last step where you say that ArrayList[] is
not a raw type.

4.8 says:

"To facilitate interfacing with non-generic legacy code, it is also
possible to use as a type the erasure (§4.6) of a parameterized type
(§4.5). Such a type is called a raw type."

4.6 on type erasure says: "The erasure of an array type T[] is |T|[]".
Where |T| means the erasure of T.

So ArrayList[] is a type erasure of ArrayList< T >[] and a raw type.

I think the confusion may be the use of the word "name" in section 4.8.
In reality ArrayList[] is "the name of a generic type declaration used
without any accompanying actual type parameters".
 
C

Chris Smith

4.8 (Raw Types) makes ArrayList[] NOT a raw type, even though its
component type is a raw type. Therefore we can't apply unchecked
conversion.
I think the problem is that last step where you say that ArrayList[] is
not a raw type.

4.8 says:

"To facilitate interfacing with non-generic legacy code, it is also
possible to use as a type the erasure (§4.6) of a parameterized type
(§4.5). Such a type is called a raw type."

Hmm.

I agree that ArrayList[] is the type erasure of ArrayList<Node>[].
However, I don't agree that ArrayList[] is "the erasure of a
parameterized type" since ArrayList<Node>[] is not a parameterized type.
§4.5 defines a parameterized type, and it doesn't include arrays whose
component type is a parameterized type.

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

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

Tony Morris

Exactly my point. The second edition has some complications (the worst I
can recall offhand being the rules for resolving method overloads), but
they can be mastered with a bit of study. This remains true for the 1.5
additions to the language other than generics.

This particular rule changed three times since JDK 1.5.0 beta and once after
JLS 3e draft was released.
 
M

Mike Schilling

Tony Morris said:
This particular rule changed three times since JDK 1.5.0 beta and once
after JLS 3e draft was released.

Sorry, which rule was that? If it's resolving method overloads with the
added complication of generics, I'm sure the result is horrific.

Pre-generics overload resolution seems to have changed something during 1.4.
It originally took the return type of an individual overload into account,
but ceased to do so.
 
D

Dale King

Chris said:
4.8 (Raw Types) makes ArrayList[] NOT a raw type, even though its
component type is a raw type. Therefore we can't apply unchecked
conversion.
I think the problem is that last step where you say that ArrayList[] is
not a raw type.

4.8 says:

"To facilitate interfacing with non-generic legacy code, it is also
possible to use as a type the erasure (§4.6) of a parameterized type
(§4.5). Such a type is called a raw type."

Hmm.

I agree that ArrayList[] is the type erasure of ArrayList<Node>[].
However, I don't agree that ArrayList[] is "the erasure of a
parameterized type" since ArrayList<Node>[] is not a parameterized type.
§4.5 defines a parameterized type, and it doesn't include arrays whose
component type is a parameterized type.

I certainly agree that section 4.5 still needs lots of work. It seems
very much a work in progress which is apparent by all the discussion
sections. But I think it is a stretch to say that ArrayList<Node>[] is
not a parameterized type. It is quite obviously a parameterized type.

I note that in 4.3 it says that an array is a reference type and
"Reference types may be parameterized (§4.5) with type arguments (§4.4)".

I went to see if this has been cleared up for 1.6, but the docs for 1.6
point to the old pre-generic JLS.

The 3rd edition of the JLS is supposedly not published yet and there is
a feedback form on the website, so you might want to feed back that they
need to be more precise.
 
C

Chris Smith

Dale King wrote ...
I certainly agree that section 4.5 still needs lots of work. It seems
very much a work in progress which is apparent by all the discussion
sections. But I think it is a stretch to say that ArrayList<Node>[] is
not a parameterized type. It is quite obviously a parameterized type.

It's certainly not "obviously" a parameterized type. Perhaps you're
right that it's intended to be one, but on several readings I still
can't find an interpretation that makes ArrayList<Node>[] fit that
definition of a parameterized type. It's actually rather obvious to me
that it is, in fact, NOT a parameterized type. You may disagree, but
it's certainly not a stretch, and it's certainly far from obvious in the
other direction.
I note that in 4.3 it says that an array is a reference type and
"Reference types may be parameterized (§4.5) with type arguments (§4.4)".

That's interesting, to be sure. I'm not sure what to think of it. It's
certainly written to imply that all three kinds of types may have
arguments, and yet the snippets of grammar right below say very clearly
otherwise.

In the end, though, the type is not ArrayList[]<Node> (which would be
illegal anyway), but rather ArrayList<Node>[]. In other words, it
doesn't have type arguments. We could surmise that the JLS is using
some kind of strange terminology that a type "has type arguments" if
there are type arguments anywhere lexically inside the definition of the
type, but that wouldn't be a very useful sort of terminology. Rather,
it appears that the statement you quoted is true, but a stronger
statement -- "All reference types may be parameterized with type
arguments" -- is not true. In particular, array types never have type
parameters.

In either case, 4.5 is very specific: a parameterized type is a class or
interface name, and then a list of type parameters. No arrays are
possible, whether are not arrays are also considered to have type
parameters.
The 3rd edition of the JLS is supposedly not published yet and there is
a feedback form on the website, so you might want to feed back that they
need to be more precise.

I have a print copy of the JLS 3rd edition, so it is published at least
under the common definition of that term. If it's still tentative,
that's interesting. I haven't seen anything like that.
 
M

Mike Schilling

Chris Smith said:
Dale King wrote ...
I have a print copy of the JLS 3rd edition, so it is published at least
under the common definition of that term. If it's still tentative,
that's interesting. I haven't seen anything like that.

I have it as well. It's not labeled "rough draft" but it certainly reads
like one..
 

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

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,045
Latest member
DRCM

Latest Threads

Top