Swing in a better world: Generics and arrays
Generics doesn't work well with arrays. Everybody knows that you can't create a generified array,
but not many people really know what it was done this way.
A nice article from Brian Goetz helped me to understand the problem
when I studied the new features of JDK 5.
String stringArray[] = new String[1];
// compiles ok
Object objectArray[] = stringArray;
// throws ArrayStoreException
objectArray[0] = new Object();
ArrayList<String> stringList = new ArrayList<String>();
// doesn't compile - incompatible types
ArrayList<Object> objectList = stringList;
If a generfied program is compiled without a warning you can safely add an Object to your ArrayList of Objects.However when there is an array of Objects passed to your method as a parameter, there is no way to understand an object of what type you can put there
(I am not sure if you can find it out via reflection).
So it is known that arrays and generics don't do well together. It means that it is not recommended to use two features of JDK 5 together,
I am talking about generics and varargs. This reminds me one old bug found by Rémi Forax,
which was fixed by changing
protected void process(V... chunks) {
}
to
protected void process(List<V> chunks) {
}
in the SwingWorker class, which did look awkward at the first glance.
An alternative implementation
I would be happy if I could create and safely use generified arrays in java, at the same time I can hardly remember if I ever saw a snippet of code that really benefited from the fact that arrays are covariant.
This feature of java arrays doesn't look attractive to me and I don't mind "deprecating" it, I don't feel it is correct that I can't create a generifed array when I never cast an array of one particular type to an array of its supertype.
Certainly all java code must be backward compatible with any new version of JDK,
I am thinking about a new warning produced by the compiler when covariant arrays are in use.
If there is no such a warning in your code it should be pretty acceptable to create a generified array, otherwise you are warned just like when you use a raw type of a generifed class. Something to discuss for the next JDKs?
This was an entry from the Swing in a better world series
Thanks
alexp
- Login or register to post comments
- Printer-friendly version
- alexfromsun's blog
- 1386 reads






Comments
<p> to create a generic array you must ...
by hute37 - 2011-05-06 08:27
to create a generic array you must "reify" yourself the type with a Class<T> parameter to a genetic utility static method, that force a cast of the result of
<a href="http://download.oracle.com/javase/6/docs/api/java/lang/reflect/Array.html#newInstance(java.lang.Class, int)">java.lang.reflect.Array.newInstance()</a>something like
usage:
<p>Hi hut37,<br /> as Alex said, generics and reflection ...
by forax - 2011-05-09 12:23
Hi hut37,
as Alex said, generics and reflection doesn't play well together.
try:
Object[] array = makeArray(int.class, 3);
Rémi
Hello <br/><br/> The problem is not how to find a trick ...
by alexfromsun - 2011-05-07 03:38
Hello
The problem is not how to find a trick and create a generified array, but the fact that it can't be used after that in a type-safe manner
Thanks
alexp
<p>Hi Alex,</p> <p>> I can hardly remember if I ever saw ...
by forax - 2011-05-06 02:48
Hi Alex,
> I can hardly remember if I ever saw a snippet of code that really benefited from the fact that arrays are covariant
I don't agree. It's easy to find such snippet.Arrays.asList() is often used with an array of something which is not an Object. Also it's not that hard to find an example of array covariance in Swing.I remember trying to generify java.swing.tree and have some trouble with bad interactions between TreePath and DefaultTreeModel, so by example in DefaultTreeModel.nodeChanged, fireTreeNodeChanged is called with an array of TreeNode but takes an array of Object as parameter.
Anyway, you're fundamentally right that the bad interactions between generics and array is a part of the Java technical debt. I really hope that Java 9 will reified generics to reduce that debt to something moderate. Currently, this debt makes all attempts to move forward less easier than it should be. The actual discussions about lambda implementations is all about that.
Note that one way to reduce the debt is also to cut spending, what about deprecating wildcards ?
Rémi
<pr/> > It's easy to find such snippet.Arrays.asList() is ...
by alexfromsun - 2011-05-06 08:10
I was talking about the situation when an array of a particular type is casted to an array of its supertype
> and DefaultTreeModel, so by example in DefaultTreeModel.nodeChanged, fireTreeNodeChanged is called with an array of TreeNode but takes an array of Object as parameter.
Yep, it is possible to find this kind of code in Swing, but it looks more like just an accident
>Note that one way to reduce the debt is also to cut spending, what about deprecating wildcards ? I personally like wildcards and would like to focus on generics and arrays in this entry Thanks much and have a great weekend!that example with array of Objects instead of TreeNodes is just an API misdesign
alexp