IveCal said:
Hi all,
Please help again. I need to resolve this issue. Why is this code not
allowed:
Gen<Integer> intGen[] = new Gen<Integer>[10];
According to the book I read by Schildt: "Arrays of specific generic
types simply aren't allowed, because they can lead to a loss of type
safety."
I understand what type safety means but I dont get in what WAY does
type safety compromised in THIS SITUATION.
My longer discussion is below. This is all new to me, but from my reading
tonight, and my testing, I can't find any reason to explain why it's not
allowed or why it's not safe.
new Gen<Integer>[10]
is just not allowed by the compiler but I don't have a clue why they choose
to reject that.
However you can do this:
Gen<Integer> intGen[] = new Gen[10];
It will produce an unchecked warning, which you can just ignore. It will
still do full generic checks on everything you do with intGen and on
everything you put into or take out of the array as far as I can tell.
As far as I can tell, doing the above, will make your code safer, than not
using generics and just defining it like this:
Gen intGen[] = new Gen[10];
Java experts please do help.
I'm no expert BTW, I'm just learning Java.
This has been an interesting learning experience for me. Generics are
still such a mystery to me when you get down to these sorts of odds
problems.
I spent a few hours reading multiple pages on this and I can't for the life
of me figure out why that isn't allowed in Java. All the pages I've read
simply translate to "it's not allowed" and none of them really explain why
it's not allowed to my satisfaction.
Generics are a compile time feature, and not a run time feature as I
understand it. And I don't see why the same rules used at compile time for
generic objects can't also be used for generic arrays.
Playing with some test code, I discovered that you can in fact use generics
for Arrays for the most part. While you can't do this:
List<Integer> li[] = new ArrayList<Integer>[10];
You can do this:
List<Integer> li[] = new ArrayList[10];
It will produce an unchecked warning, but it will compile. Not only that,
but when you use the array variable li, and when you try to use li[n], it
will, as far as I can tell, correctly honor all the normal generic
restrictions.
For example, if you try this:
List<Number> ln[];
ln = li;
It will produce a compile error as you would want it to where as without
the generic definitions, it would of course have allowed it.
And if you try this:
li[0].add("string");
It will produce a compile as expected based on the generic definition of
li.
So as far as I can see, everything I tested with generic arrays works as
expected. You get compile errors if you try to do something that's a
violation of the generic definition of the array.
The only thing I've found that doesn't work, is the new statement, and I
don't understand why they choose to make everything else work, and not
allow you to use a generic new statement. So as far as I can see, you can
use generics with arrays, and the compiler does do all the checking for
you, but the only real drawback, is that you are forced to live with
unchecked exception warnings when you create the array.
I'm sure there's something I'm missing, but I don't know what it is yet.
Part of it might be the fact that arrays already have run-time support for
type checking. Arrays are in effect collection objects already, but unlike
the normal collection objects, Java included run time type checking of
arrays. That is, arrays know what type of object can be stored in them,
and will throw a ArrayStoreException at run time if you try to put the
wrong thing in them:
String[] sa = new String[10];
// acts much like: Array<String> sa = new Array<String>(10);
// so in effect, arrays are a limited form of generics already.
Object oa[] = sa; // Generics would reject this, but java allows
it
oa[0] = new Object(); // compiles fine, but throws
ArrayStoreException
// the jvm won't let you put an object into a string array even without
// generics.
So at run time, the string array "knows" it's a string array and will throw
an exception if you make an error. In effect, Arrays already have
generic-like type safety built into at run time.
Generics were added for the purpose of adding safety to the Collection
objects which before Generics had no compile time checks at all.
So I wonder if the Java designers simply didn't think of making Generics
work for Arrays since they are such a different beast to start with and
since arrays already have their own version of type safety done a different
way. Maybe they were thinking that to add generics to arrays, they would
have to extend the run time check system of arrays to support full generic
types, and since they didn't plan to make run time changes to support
generics, they say it as something they just couldn't add to arrays? But
from what I understand, I don't see why that is true because I don't
understand why all the same compile time rules used for generic objects
can't be correctly applied to generic arrays - and as I saw in my testing,
it seems the compiler is actually correctly applying those compile time
rules to generic arrays.
It's all very interesting and mystical still to me. But, the end result,
is that you can define, and use, generic arrays, you just can't create them
without a compile error - you have to create them as non generic arrays and
live with the compile time warning when you assign them to the generic
array variable. I can't believe it is any less safe to do that than to not
use a generic definition of the array.
However, if you want compile time generic safety for Arrays, it seems to me
the best solution is to not use arrays, and just use an ArrayList (or other
collection object) instead.