Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / May 2006

Tip: Looking for answers? Try searching our database.

Yet Another ClassCastException Question

Thread view: 
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 Magazines

Get 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 ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.