Java Forum / General / June 2006
Java generic issue in array
jacksu - 25 May 2006 20:58 GMT 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.
nkalagarla@gmail.com - 25 May 2006 21:50 GMT generic array creation is not allowed.Try following work-around.
ArrayList<Node>[] myarr = (ArrayList<Node>[]) Array.newInstance(ArrayList.class,n);
> I could create: > [quoted text clipped - 8 lines] > > Thanks. Luc The Perverse - 25 May 2006 22:02 GMT > 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[i] = new ArrayList<Node>(); //initialize each individually
-- LTP
:) nkalagarla@gmail.com - 25 May 2006 22:29 GMT 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.
:) Chris Smith - 25 May 2006 22:52 GMT > 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.
 Signature www.designacourse.com The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer MindIQ Corporation
Mike Schilling - 25 May 2006 23:17 GMT >> 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 [quoted text clipped - 6 lines] > 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];
Chris Smith - 25 May 2006 23:39 GMT > 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. :)
 Signature www.designacourse.com The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer MindIQ Corporation
Mike Schilling - 28 May 2006 06:03 GMT >> ArrayList<Node>[] myarr = new ArrayList[n]; > [quoted text clipped - 6 lines] > 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.
Chris Smith - 28 May 2006 15:37 GMT > 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?
 Signature www.designacourse.com The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer MindIQ Corporation
Mike Schilling - 28 May 2006 17:36 GMT >> If you're implying that you'd understand it after you read the spec, it >> must [quoted text clipped - 4 lines] > 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.
Tony Morris - 30 May 2006 23:40 GMT > 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.
 Signature Tony Morris http://tmorris.net/
Mike Schilling - 30 May 2006 23:58 GMT >> Exactly my point. The second edition has some complications (the worst I >> can recall offhand being the rules for resolving method overloads), but [quoted text clipped - 3 lines] > 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.
Dale King - 30 May 2006 15:02 GMT >> 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. [quoted text clipped - 46 lines] > 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".
 Signature Dale King
Chris Smith - 30 May 2006 17:07 GMT > > 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. [quoted text clipped - 4 lines] > 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.
 Signature www.designacourse.com The Easiest Way To Train Anyone... Anywhere.
Chris Smith - Lead Software Developer/Technical Trainer MindIQ Corporation
Dale King - 31 May 2006 01:24 GMT >>> 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 [quoted text clipped - 16 lines] > §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.
 Signature Dale King
Chris Smith - 31 May 2006 06:40 GMT > 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.
 Signature Chris Smith
Mike Schilling - 31 May 2006 08:26 GMT >> 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. I have it as well. It's not labeled "rough draft" but it certainly reads like one..
Dale King - 31 May 2006 15:44 GMT > 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. I did some more reading and think perhaps it is not a question of whether it is parameterized, but whether it is reifiable. And I must say that the reifiable discussion is very fuzzy to me. They have a section in chapter 4 on it, but the word is not even used in chapter 5.
The question is whether you consider ArrayList[] to be a raw type. 4.8 says a raw type is "The name of a generic type declaration used without any accompanying actual type parameters." I think that would be applicable. This gives us a path through section 5.2 (identity conversion followed by unchecked conversion because it is a raw type).
At the end of chapter 10 on arrays in the section on the runtime ArrayStoreException it has a discussion section that says:
"If the element type of an array were not reifiable (§4.7), the virtual machine could not perform the store check described in the preceding paragraph. This is why creation of arrays of non-reifiable types is forbidden. One may declare variables of array types whose element type is not reifiable, but any attempt to assign them a value will give rise to an unchecked warning (§5.1.9)."
According to 4.7 ArrayList<Node>[] is not reifiable and so any attempt to assign to it should give the unchecked warning. It would be nice if this information were incorporated into section 5.1.9.
>> 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 [quoted text clipped - 3 lines] > under the common definition of that term. If it's still tentative, > that's interesting. I haven't seen anything like that. I'm just going by what the website said. I see now that it is just out of date information since it says "the physical book should be available in June 2005."
It would still be a good idea to provide feedback that they might add some errata or clarification.
 Signature Dale King
Chris Smith - 01 Jun 2006 18:24 GMT > I did some more reading and think perhaps it is not a question of > whether it is parameterized, but whether it is reifiable. And I must say [quoted text clipped - 6 lines] > applicable. This gives us a path through section 5.2 (identity > conversion followed by unchecked conversion because it is a raw type). Yes, it would. I was using the earlier definition from the previous sentence ("type erasure of a parameterized type"). The spec claims that this second definition is more precise; I disagree, since I don't see any clear definition of what constitutes a generic type declaration. However, for the sake of discussion and because implementations seem to support it, we'll adopt your view that ArrayList[] is the name of a generic type declaration. Still, unchecked conversion (5.1.9) presents a problem, since the target of unchecked conversion is a parameterized type, and I previously explained why I don't think that ArrayList<Node>[] is a parameterized type.
> At the end of chapter 10 on arrays in the section on the runtime > ArrayStoreException it has a discussion section that says: [quoted text clipped - 5 lines] > is not reifiable, but any attempt to assign them a value will give rise > to an unchecked warning (§5.1.9)." Yes, so this seems to say that 5.1.9 ought to apply to conversion of array types. I believe this is an internal contradiction within the language specification. There is no way to reconcile the above statement with the definition of unchecked conversion in 5.9 and the definition of a parameterized type in 4.5. Although the section you quote is non-normative, it still indicates a problem in that the actual consequences of the language spec conflict not only with existing implementations, but also with the clearly stated intent of the specification itself.
> It would still be a good idea to provide feedback that they might add > some errata or clarification. Yes, I agree.
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
Dale King - 02 Jun 2006 15:00 GMT >> I did some more reading and think perhaps it is not a question of >> whether it is parameterized, but whether it is reifiable. And I must say [quoted text clipped - 37 lines] > implementations, but also with the clearly stated intent of the > specification itself. Then I think we are in agreement. It is clear from the JLS that the assignment should be allowed, but the JLS is not being precise enough for a language lawyer and could definitely be cleaned up and made more explicit.
 Signature Dale King
Chris Smith - 02 Jun 2006 19:26 GMT > Then I think we are in agreement. It is clear from the JLS that the > assignment should be allowed, but the JLS is not being precise enough > for a language lawyer and could definitely be cleaned up and made more > explicit. Yes, in a way. I'd add the caveat that the only thing that convinces me that allowing the assignment is intended to be legal is the non- normative "Discussion" section at the end of chapter 10... that and the behavior of the current implementation. I think I'd use the word "fix" rather than "clean up."
 Signature Chris Smith - Lead Software Developer / Technical Trainer MindIQ Corporation
Mike Schilling - 02 Jun 2006 20:50 GMT >> Then I think we are in agreement. It is clear from the JLS that the >> assignment should be allowed, but the JLS is not being precise enough [quoted text clipped - 5 lines] > normative "Discussion" section at the end of chapter 10... that and the > behavior of the current implementation. And that, naively, you'd expect it be allowed (or I would, anyway.) There's a lot to be said for Least Astonishment.
Tony Morris - 26 May 2006 02:17 GMT >I could create: > [quoted text clipped - 8 lines] > > 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.
 Signature Tony Morris http://tmorris.net/
Mike Schilling - 26 May 2006 19:07 GMT > 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.
Thomas Hawtin - 26 May 2006 10:24 GMT > I could create: > [quoted text clipped - 4 lines] > 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
 Signature Unemployed English Java programmer http://jroller.com/page/tackline/
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|