 |
Did I Miss Generic Array Creation?
Posted by dwalend on January 07, 2005 at 05:07 AM | Comments (10)
While sweeping up sawdust before the latest release of JDigraph, I used -Xlint to spot remaining places where I have some things to clean up. I have just a handful to go. I'm having the most trouble with creating Arrays in collection-like classes. JDigraph is a generic efficient directed graph representation, so these arrays are everywhere. I've taken examples from FibHeap.java.
HeapMember<Key,Value,Comp$gt;[] fibNodes = (HeapMember<Key,Value,Comp>[])Array.newInstance(HeapMember.class,size());
results in a waring from lint.
The first thing I tried didn't compile:
//doesn't compile
HeapMember<Key,Value,Comp>[] fibNodes = new HeapMember<Key,Value,Comp>[size()];
results in
jdigraph/v2/source/collection/net/walend/collection/FibHeap.java:57: generic array creation
HeapMember<Key,Value,Comp>[] fibNodes = new HeapMember<Key,Value,Comp>[size()];
I tried dynamically creating the array using java.lang.reflect.Array:
HeapMember<Key,Value,Comp>[] fibNodes = (HeapMember<Key,Value,Comp>[])Array.newInstance(HeapMember.class,size());
which gives me the warning from lint again.
/Users/dwalend/projects/opensource/jdigraph/v2/source/collection/net/walend/collection/FibHeap.java:58: warning: [unchecked] unchecked cast
found : java.lang.Object
required: net.walend.collection.HeapMember<Key,Value,Comp>[]
HeapMember<Key,Value,Comp>[] fibNodes = (HeapMember<Key,Value,Comp>[])Array.newInstance(HeapMember.class,size());
I've tried doing other things, especially to the HeapMember.class argument, but haven't found a solution that compiles with no warnings.
Is there some bit of API I missed? Is there a good reason not to create arrays of generics? Or should I report a RFE to Sun asking them to add generic parameters to Array.newInstance()?
Thanks,
Dave
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
section 7.3 of the tutorial seems to cover this?
http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf
in summary, it sounds like because the true parameterized type in unknown at run-time you don't have enough information to guarantee run-time type safety, so you have to be disallow more than you'd like
(possibly)
btw, isn't forums.java.sun.com the place for this sort of question?
Posted by: asjf on January 07, 2005 at 05:55 AM
-
asjf,
The end of section 7.3 of the tutorial says section 8 will explain a work-around to avoid the warning. To use section 8, I'd need a way to say
HeapMember<Key,Value,Comp>.class either a newArray(size) method on Class or a type-aware newInstance() method on Array. That's why I think there's a missing piece.
pprun,
Thanks for the pointer. I'd rather not use @SuppressWarnings("unchecked") . Just one method, but it'd leave me feeling a little dirty.
Thanks again,
Dave
Posted by: dwalend on January 07, 2005 at 07:06 AM
-
public class ArrayFactory
{
private ArrayFactory() {}
public static T[] toArray( T... array )
{
return array;
}
}
Posted by: wingetr on January 07, 2005 at 06:54 PM
-
I've run into the same problem. I think the bug is with the compiler's -Xlint option (which was added late in the release), rather than the language itself. I'm not a Java language expert, however.
Posted by: tball on January 08, 2005 at 10:04 AM
-
wingetr,
That's a nice hack, but doesn't quite fit my problem. However, that plus pprun's post did inspire my own hack:
@SuppressWarnings("unchecked")
private HeapMember[] createHeapMemberArray(int size)
{
return (HeapMember[])Array.newInstance(HeapMember.class,size);
}
private void consolidate()
{
HeapMember[] fibNodes = createHeapMemberArray(size());
...
I decided that a one-line method with one unchecked cast is OK for now.
tball,
Looks like Sun ran out of time to fix the -Xlint option to actually look at @SuppressWarnings("unchecked"). So my hack will help reduce warnings in classes that have the same unchecked cast, but won't get rid of all warnings. See bug #4986256, and add a vote if you've got one to spare.
And I'll go ahead and put in the RFE for a typesafe Array.newInstance(). Will post the bug number once it works its way through the parade.
Thanks,
Dave
Posted by: dwalend on January 08, 2005 at 10:33 AM
-
T[].class.cast(java.lang.reflect.Array.newInstance(T[].class, size));
Posted by: kinfei on September 05, 2006 at 12:32 AM
-
Thanks for the suggestion, kinfei. It still gives the warning. You can't specify the generics on T[] in the T[].class.
Thanks for the suggestion in this old blog, though.
Dave
Posted by: dwalend on September 06, 2006 at 06:07 AM
-
As I read in http://sofpower.com/java/qa.html, this is a common problem. Quoting sofpower.com:
"Q: Why does E[] arr = new E[cap]; give a compile-time error?
A: Basically, the operator new is a run-time operation and Java 1.5 removes all generics typing at compile-time. This is the well-known generic array creation an operation not supported by Java 1.5. You need to use
obj = (E[]) (new Object[cap]);
which will compile with just a warning."
Regards,
Duilio Protti.
Posted by: dprotti on May 07, 2007 at 06:54 AM
-
dprotti,
Thanks for posting in this ancient blog. I'm at JavaOne where we're going to have an "animated discussion" about getting rid of erasure for JDK7.
For now, the cast is the best you can do. I put the casts like that in a short separate private method with a @SuppressWarning( "unchecked" ) annotation. That works well for me.
Dave
Posted by: dwalend on May 07, 2007 at 07:46 AM
|