Java Forum / General / May 2006
Yet Another ClassCastException Question
Michael Powe - 01 May 2006 04:29 GMT I have an ArrayList initialized thus:
ArrayList<Date> entryDate = new ArrayList<Date>();
And used in this method:
Date [] sortEntryKeys(ArrayList entryDate){ Date [] sortedEntryDates = null; Collections.sort(entryDate); sortedEntryDates = (Date []) entryDate.toArray(); return sortedEntryDates;
The cast to sortedEntryDates throws a ClassCastException when the method is invoked on an ArrayList of Date objects.
Why? I have another, clunky way of getting the dates into the array, using System.arraycopy(), but I'd like to know why this way does not work.
Thanks.
mp
 Signature 'cat' is not recognized as an internal or external command, operable program or batch file.
Patrick - 01 May 2006 07:32 GMT Michael Powe a écrit :
> ArrayList<Date> entryDate = new ArrayList<Date>(); > > sortedEntryDates = (Date []) entryDate.toArray(); > > The cast to sortedEntryDates throws a ClassCastException when the > method is invoked on an ArrayList of Date objects. The toArray method returns an array of Object, not Date. You must write: sortedEntryDates = (Date []) entryDate.toArray(new Date[0]);
RTFM: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collection.html#toArray(T[])
 Signature Patrick
Mike Schilling - 01 May 2006 07:34 GMT >I have an ArrayList initialized thus: > [quoted text clipped - 14 lines] > using System.arraycopy(), but I'd like to know why this way does not > work. You didn't tell toArray what sort of array to create, so it created an Object[]. Try
sortedEntryDates = (Date []) entryDate.toArray(new Date[entryDate.size()]);
Michael Powe - 01 May 2006 10:47 GMT >>>>> "Mike" == Mike Schilling <mscottschilling@hotmail.com> writes: Mike> "Michael Powe" <michael+gnus@trollope.org> wrote in message Mike> news:ulktmjud6.fsf@trollope.org...
>> The cast to sortedEntryDates throws a ClassCastException when >> the method is invoked on an ArrayList of Date objects.
>> Why? I have another, clunky way of getting the dates into the >> array, using System.arraycopy(), but I'd like to know why this >> way does not work.
Mike> You didn't tell toArray what sort of array to create, so it Mike> created an Object[]. Try
Mike> sortedEntryDates = (Date []) entryDate.toArray(new Mike> Date[entryDate.size()]);
Okay, great, that worked. What am I missing about casting from Object to Date? I've looked at some discussions of casting in my books but it is not clear to me -- in fact, from my reading it would seem that it should work. (converting object[] to date[]).
Thanks for the help.
mp
 Signature Michael Powe michael@trollope.org Naugatuck CT USA
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
Bjorn Abelli - 01 May 2006 13:31 GMT > What am I missing about casting from Object > to Date? Probably nothing, but that's another casting.
Here you're trying to cast arrays: Object[] to Date[]
That casting would be okay, if the original array was *initialized* as a Date[].
Some examples; to show the problem I instantiate two arrays:
Object[] oad = new Date[];
Object[] oao = new Object[];
Now we try to cast them:
The first cast will work, as it *is* a Date[].
Date[] dad = (Date[]) oad;
The second cast won't work, as there *could* be instances of other types in the array, even if there isn't:
Date[] dao = (Date[]) oao; // Won't work!
That's why you need to provide the right type of array into ToArray when you want a specific type of array.
// Bjorn A
Oliver Wong - 01 May 2006 18:41 GMT > to show the problem I instantiate two arrays: > > Object[] oad = new Date[]; I wasn't aware you could do this. I thought to myself "But what if I then try to put a String into oad?" So I tried it out, and I got a runtime ArrayStoreException. To me, this looks like a pretty ugly language design.
- Oliver
Bjorn Abelli - 01 May 2006 19:11 GMT "Oliver Wong" wrote...
> "Bjorn Abelli" wrote... >> [quoted text clipped - 3 lines] > > I wasn't aware you could do this. Well, not *exactly*.
You need to provide an array dimesion too.
I only wrote it hastily to show the consequences and omitted that... ;-)
But otherwise it's all according to the specs.
> I thought to myself "But what if I then try to put a String into oad?" > So I tried it out, and I got a runtime ArrayStoreException. To me, this > looks > like a pretty ugly language design. Well, I think it's actually better with that "stricter" typesafety than the similar construction with "generic" collections. I tested the following snippet in 1.6:
ArrayList old = new ArrayList<Date>();
old.add("foo");
?
;-)
// Bjorn A
Timo Stamm - 01 May 2006 19:30 GMT Bjorn Abelli schrieb:
> "Oliver Wong" wrote... >> I thought to myself "But what if I then try to put a String into oad?" [quoted text clipped - 9 lines] > > old.add("foo"); This is not a valid comparison. The compiler warns you about the usage of the raw type in the above code. A valid complement to
Object[] oad = new Date[];
is
ArrayList<Object> old = new ArrayList<Date>();
and this gives you an error.
Timo
Bjorn Abelli - 01 May 2006 20:03 GMT "Timo Stamm" wrote...
> Bjorn Abelli schrieb: >> "Oliver Wong" wrote... [quoted text clipped - 12 lines] > > This is not a valid comparison. That's why I added the smiley at the end, in case anyone spotted that... ;-)
> The compiler warns you about the usage of the raw type in the above code. But my point is really that I think it's a confusing aspect that the attempt to instantiate the ArrayList as an ArrayList<Date> is ignored and silently "overridden" by the declared type, a "raw" ArrayList.
I would feel more comfortable if the compiler actually gave an *error* also in that case, or at least a warning.
// Bjorn A
Timo Stamm - 01 May 2006 20:23 GMT Bjorn Abelli schrieb:
> "Timo Stamm" wrote... >> Bjorn Abelli schrieb: [quoted text clipped - 13 lines] > > That's why I added the smiley at the end, in case anyone spotted that... ;-) Sorry, I missed it :)
>> The compiler warns you about the usage of the raw type in the above code. > [quoted text clipped - 4 lines] > I would feel more comfortable if the compiler actually gave an *error* also > in that case, or at least a warning. Yes, that would have been better.
Mike Schilling - 01 May 2006 20:51 GMT > Bjorn Abelli schrieb: >> "Oliver Wong" wrote... [quoted text clipped - 21 lines] > > and this gives you an error. Generics work differently than arrays, and this is going to cause confusion now and for the rest of Java's lifetime.
Date[] dad = newDate[12] Object[] oad = dad;
is perfectly safe, because
oad[1] = new Object();
will cause an ArrayStoreException then and there. No data structures will be corrupted and no subtle bugs introduced.
On the other hand
ArrayList<Date> dal = new ArrayList<Date>(); ArrayList<Object> oal = (ArrayList<Object>)dal;
is unsafe, because
oal.add(new Object());
will succeed, and only at some later time will
Date d = dal.get(12);
throw an exception, making it clear that there's been a problem *somewhere*.
Mike Schilling - 01 May 2006 20:18 GMT >> to show the problem I instantiate two arrays: >> [quoted text clipped - 3 lines] > then try to put a String into oad?" So I tried it out, and I got a runtime > ArrayStoreException. To me, this looks like a pretty ugly language design. It's a compromise. If Java had the notion of "read-only" array references, that would be better:
Object[~write] oad = new Date[];
But imagine a Java in which
Object[] oad = new Date[];
was illegal; you couldn't use System.arraycopy().to copy things into Date arrays, because it's declared as taking parameters that are Object arrays.
Mike Schilling - 01 May 2006 16:16 GMT >>>>>> "Mike" == Mike Schilling <mscottschilling@hotmail.com> writes: > [quoted text clipped - 18 lines] > it is not clear to me -- in fact, from my reading it would seem that > it should work. (converting object[] to date[]). Nothing. What you're missing is that arrays (unlike generic collections) have actual run-time types. Object[] and Date[] are different types, just as Object and Date are, and casting from the former to the latter can fail.
Object[] oa = new Object[1]; Date[] da = new Date[1];
Object[] oa2 = da; // allowed Date[] da2 = (Date[])oa2; // works, since it's "really" a Date[] Date[] da3 = (Date[])oa; // fails at runtime with a ClassCastException // since it's "really" an Object[]
Michael Powe - 01 May 2006 22:10 GMT >>>>> "Mike" == Mike Schilling <mscottschilling@hotmail.com> writes: >> Okay, great, that worked. What am I missing about casting >> from Object to Date? I've looked at some discussions of >> casting in my books but it is not clear to me -- in fact, from >> my reading it would seem that it should work. (converting >> object[] to date[]).
Mike> Nothing. What you're missing is that arrays (unlike generic Mike> collections) have actual run-time types. Object[] and Mike> Date[] are different types, just as Object and Date are, and Mike> casting from the former to the latter can fail.
Mike> Object[] oa = new Object[1]; Date[] da = new Date[1];
Mike> Object[] oa2 = da; // allowed Mike> Date[] da2 = (Date[])oa2; // works, since it's "really" a Mike> Date[] Mike> Date[] da3 = (Date[])oa; // fails at runtime with a Mike> ClassCastException // since it's "really" an Object[]
Okay, that makes sense. I appreciate the discussion, it clarified things for me. I actually had seen in the Sun Java forums that bad piece of code put out as something 'that works for me' and nobody contested it there -- and then I missed the significance in other discussions of the .toArray( Date []) piece. The javadoc is not clear, either.
Thanks.
mp
 Signature Michael Powe michael@trollope.org Naugatuck CT USA
Sometimes I worry about being a success in a mediocre world. -- Lily Tomlin
Mike Schilling - 02 May 2006 04:18 GMT > Okay, that makes sense. I appreciate the discussion, it clarified > things for me. I actually had seen in the Sun Java forums that bad > piece of code put out as something 'that works for me' and nobody > contested it there -- and then I missed the significance in other > discussions of the .toArray( Date []) piece. The javadoc is not > clear, either. The javadoc says:
toArray
public Object[] toArray(Object[] a)
Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array. If the collection fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this collection.
That's probably clear if and only if you're already familiar with the concept of "runtime type of an array".
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 ...
|
|
|