Array of ArrayLists problem

R

Ross

Let's say that I have a java.util.ArrayList which will contain only
strings. So, I can declare this as:

ArrayList<String> blah = new ArrayList<String>();

So far so good, but let's say that blah is an array in itself. I'd
expect to be able to do this:

ArrayList<String> blah[] = new ArrayList<String>[ 50 ];

However, if I do that, I get a compile time error saying something
about creating a generic array. If I modify the code to:

ArrayList<String> blah[] = new ArrayList[ 50 ];

Then, it compiles and works, but gives me a warning about using a
deprecated blah blah blah.

What gives?
 
L

Lew

Ross said:
Let's say that I have a java.util.ArrayList which will contain only
strings. So, I can declare this as:

ArrayList<String> blah = new ArrayList<String>();

So far so good, but let's say that blah is an array in itself. I'd
expect to be able to do this:

ArrayList<String> blah[] = new ArrayList<String>[ 50 ];

However, if I do that, I get a compile time error saying something
about creating a generic array. If I modify the code to:

ArrayList<String> blah[] = new ArrayList[ 50 ];

Then, it compiles and works, but gives me a warning about using a
deprecated blah blah blah.

What gives?

Arrays and generics don't mix. It has to do with arrays being
reifiable but not generics.

From the JLS, §10.10:
"... creation of arrays of non-reifiable types is forbidden."
<http://java.sun.com/docs/books/jls/third_edition/html/
arrays.html#10.10>
 
M

markspace

It's a pain but Java's generics are not reifiable. Simple solution:
prefer ArrayList to arrays:


ArrayList<ArrayList<String>> arrayOfLists =
new ArrayList<ArrayList<String>>( 50 );

arrayOfLists.add( new ArrayList<String>() );

etc.
 
L

Lew

markspace said:
It's a pain but Java's generics are not reifiable.  Simple solution:
prefer ArrayList to arrays:

   ArrayList<ArrayList<String>> arrayOfLists =
       new ArrayList<ArrayList<String>>( 50 );

   arrayOfLists.add( new ArrayList<String>() );

etc.

Prefer Lists of Lists to ArrayLists of ArrayLists:

List <List <String>> holyOfHolies =
new ArrayList <List <String>> ();

holyOfHolies.add( new ArrayList <String> () );
 
M

Mike Schilling

Lew said:
Ross said:
Let's say that I have a java.util.ArrayList which will contain only
strings. So, I can declare this as:

ArrayList<String> blah = new ArrayList<String>();

So far so good, but let's say that blah is an array in itself. I'd
expect to be able to do this:

ArrayList<String> blah[] = new ArrayList<String>[ 50 ];

However, if I do that, I get a compile time error saying something
about creating a generic array. If I modify the code to:

ArrayList<String> blah[] = new ArrayList[ 50 ];

Then, it compiles and works, but gives me a warning about using a
deprecated blah blah blah.

What gives?

Arrays and generics don't mix. It has to do with arrays being
reifiable but not generics.

From the JLS, §10.10:
"... creation of arrays of non-reifiable types is forbidden."
<http://java.sun.com/docs/books/jls/third_edition/html/
arrays.html#10.10>

There aren't many instances in Java of "That's how it works. Don't ask why;
you're better off not knowing", but this is one of them.
 
L

Lew

Mike said:
There aren't many instances in Java of "That's how it works.  Don't ask why;
you're better off not knowing", but this is one of them.- Hide quoted text -

It's funny you should say that, because the JLS says why in the
section I cited.
 
K

Kevin McMurtrie

"Mike Schilling said:
Lew said:
Ross said:
Let's say that I have a java.util.ArrayList which will contain only
strings. So, I can declare this as:

ArrayList<String> blah = new ArrayList<String>();

So far so good, but let's say that blah is an array in itself. I'd
expect to be able to do this:

ArrayList<String> blah[] = new ArrayList<String>[ 50 ];

However, if I do that, I get a compile time error saying something
about creating a generic array. If I modify the code to:

ArrayList<String> blah[] = new ArrayList[ 50 ];

Then, it compiles and works, but gives me a warning about using a
deprecated blah blah blah.

What gives?

Arrays and generics don't mix. It has to do with arrays being
reifiable but not generics.

From the JLS, §10.10:
"... creation of arrays of non-reifiable types is forbidden."
<http://java.sun.com/docs/books/jls/third_edition/html/
arrays.html#10.10>

There aren't many instances in Java of "That's how it works. Don't ask why;
you're better off not knowing", but this is one of them.

I'd like to submit this one too:

-----------

public class Foo
{
class InnerFoo { }
void method ()
{
InnerFoo x[]= new InnerFoo[100]; //Compiles
}
}

-----------

public class Foo<BAR>
{
class InnerFoo { }
void method ()
{
InnerFoo x[]= new InnerFoo[100]; //Doesn't compile
}
}

-----------

public class Foo<BAR>
{
class InnerFoo { }
void method ()
{
InnerFoo x[]= new Foo.InnerFoo[100]; //Compiles
}
}
 
L

Lew

Kevin said:
[...]
public class Foo<BAR>
{
class InnerFoo { }
void method ()
{
InnerFoo x[]= new InnerFoo[100]; //Doesn't compile
}
}

Peter said:
I'd guess the answer to that may actually be specifically addressed in
the spec too.

But even if not, it seems to me that your example is just a variant on
the situation that's already being discussed. The above version of the
code involves a non-reified generic type (Foo<BAR>.InnerFoo), of which
you can't make an array, and for the same reason as indicated before.

By explicitly choosing the raw type to qualify InnerFoo, you strip the
generic and thus create a legal array type. Note that while the third
example compiles, you do get a warning about the need for an unchecked
conversion. That's only slightly better than it simply not compiling at
all.

I wonder if a non-inner nested class member would have this trouble. I also
wonder if
InnerFoo x[] = new this.InnerFoo [100];
or something along those line would work.

I'll try that later myself, along with variations for a local class (which I
expect not to). One wonders about inner classes in a static context, albeit
less so.

I've been shot down in this forum before for he suggestioon that an
inner-class definition belongs to a particular enclosing-class instance (as
opposed to the inner-class *instance* belonging to an instance), and there
definitely are limits to that mental model, but it works out to be a handy way
to look at things most times.
 
L

Lew

Lew said:
I wonder if a non-inner nested class member would have this trouble.

Nope.

I also wonder if
   InnerFoo x[] = new this.InnerFoo [100];
or something along those line would work.

Nope.

I'll try that later myself, along with variations for a local class (which I
expect not to).  

Local classes in an instance method also complain about an attempt to
instantiate a generified array.

Peter is correct. The error with instantiating an array for any
instance-level inner class in a generic containing class is that one
cannot instantiate an array of a non-reifiable type.
 
K

Kevin McMurtrie

[QUOTE="Lew said:
[...]
public class Foo<BAR>
{
class InnerFoo { }
void method ()
{
InnerFoo x[]= new InnerFoo[100]; //Doesn't compile
}
}

Peter said:
I'd guess the answer to that may actually be specifically addressed in
the spec too.

But even if not, it seems to me that your example is just a variant on
the situation that's already being discussed. The above version of the
code involves a non-reified generic type (Foo<BAR>.InnerFoo), of which
you can't make an array, and for the same reason as indicated before.

By explicitly choosing the raw type to qualify InnerFoo, you strip the
generic and thus create a legal array type. Note that while the third
example compiles, you do get a warning about the need for an unchecked
conversion. That's only slightly better than it simply not compiling at
all.

I wonder if a non-inner nested class member would have this trouble. I also
wonder if
InnerFoo x[] = new this.InnerFoo [100];
or something along those line would work.

I'll try that later myself, along with variations for a local class (which I
expect not to). One wonders about inner classes in a static context, albeit
less so.

I've been shot down in this forum before for he suggestioon that an
inner-class definition belongs to a particular enclosing-class instance (as
opposed to the inner-class *instance* belonging to an instance), and there
definitely are limits to that mental model, but it works out to be a handy
way
to look at things most times.[/QUOTE]


Eclipse says "new this.InnerFoo [100]" doesn't compile. You can use
"(InnerFoo[])Array.newInstance(InnerFoo.class, 100)"

The annoying thing about the example that I gave is that the declaration
of the array works fine. There's nothing special about allocating the
array that should make it any different when Generics are involved.

Java Generics are a handy tool but the implementation is flawed enough
that I can see it hindering future language improvements. I would have
preferred something like C++ templates even if it meant redoing a lot of
the java.util package. Besides being more powerful, it would eliminate
the need for horribly inefficient autoboxing of short, char, int, long,
float, and double.
 
L

Lew

Kevin said:
The annoying thing about the example that I gave is that the declaration
of the array works fine.  There's nothing special about allocating the
array that should make it any different when Generics are involved.

Other than the reason the JLS gives, you mean. The "something
special" is mentioned there.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top