Win a copy of Programmer's Guide to Java SE 8 Oracle Certified Associate (OCA) this week in the OCAJP forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Object[] to Long[]

 
Jacob Sonia
Ranch Hand
Posts: 183
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a Long[] array and a Set<Long> and i try to do this:

Long[] arr = (Long[])set.toArray();

It throws a ClassCastException. Please tell me why does it do that and how can i achieve what i am trying to do?
 
Tim McGuire
Ranch Hand
Posts: 820
IntelliJ IDE Tomcat Server VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jacob Sonia wrote:I have a Long[] array and a Set<Long> and i try to do this:

Long[] arr = (Long[])set.toArray();

It throws a ClassCastException. Please tell me why does it do that and how can i achieve what i am trying to do?


arrays cannot be cast like other Objects as Long[] does not inherit from Object[].

one way to do it is:

Long[] arr = set.toArray(new Long[0]);

Check out http://java.sun.com/javase/6/docs/api/java/util/Set.html#toArray%28%29
 
Henry Wong
author
Marshal
Pie
Posts: 21412
84
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jacob Sonia wrote:I have a Long[] array and a Set<Long> and i try to do this:

Long[] arr = (Long[])set.toArray();

It throws a ClassCastException. Please tell me why does it do that and how can i achieve what i am trying to do?


The toArray() method returns an Object[] with Long objects as it's elements. It doesn't return a Long[], hence, can't be casted. To make it return an Long[], use the other (overloaded) toArray() method.

Henry
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24212
35
Chrome Eclipse IDE Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim McGuire wrote:

arrays cannot be cast like other Objects as Long[] does not inherit from Object[].



Although the rest of what Tim says is true, this actually is not: Long[] does inherit from Object[]. You can't do the cast for the same reason that you can't cast "new Object()" to a Long.

Many people consider this inheritance setup a flaw in the language -- the design of generics was specifically arranged to learn from this mistake and avoid the issues this inheritance causes.
 
Rob Spoor
Sheriff
Pie
Posts: 20608
63
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I wouldn't call it inheriting. It's not like Long[].class.getSuperclass() returns Object[].class; it returns Object.class. Long[] is a subtype of Object[] though, just as Long is a subtype of Object. The term subtype is a bit broader than subclass because it also handles arrays and interfaces. For instance, ArrayList is a subtype of List because it implements List.
 
Tim McGuire
Ranch Hand
Posts: 820
IntelliJ IDE Tomcat Server VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for this clarification. This reasoning of "Long[] is not subclass of Object[] therefore casting won't work" is repeated so often in other forums, so I'm trying to grasp this other explanation.

so... here is code from the java specifications concerning casting of arrays
(http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#20232):



it says the above will compile and run. It does (well, except for there being two public types).
and this is a case of an array being cast to an array of subtypes! This does not seem to be different from our original problem as the Objects I get from
set.toArray()
resolve to type Long. and If I iterate through the array, they can be cast individually to Long.

the specs say that unless the following is true, there will be a runtime classCastException

TC and RC are reference types and type RC can be cast to TC by a recursive application of these run-time rules for casting.


so this recursive application of run time casting rules DOES happen. I thought it didn't.

so set.toArray() returns an array of Objects that can be cast to Long through a "recursive application of run-time rules for casting", right?

Now that I've talked myself out of my original answer, I do not understand why he gets a classCastException.
 
Rob Spoor
Sheriff
Pie
Posts: 20608
63
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Try changing line 21 to "Point[] pa = new Point[4];" and try again.

You can cast an Object[] to a Long[] if the Object[] is in fact a Long[]. If it is an Object[] where each element happens to be a Long it will still fail, even though the elements match the cast.
 
Tim McGuire
Ranch Hand
Posts: 820
IntelliJ IDE Tomcat Server VI Editor
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Rob Prime wrote:Try changing line 21 to "Point[] pa = new Point[4];" and try again.


I see, so inside of set.toArray() it is doing:



on line four, the method has no way to extract the type from it.next and use it, which is why we get the casting error.
and here it is obvious, as Ernest said, that having no type safety hurts, hence generics and the generic version of toArray fixes our problems.
 
Rob Spoor
Sheriff
Pie
Posts: 20608
63
Chrome Eclipse IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tim McGuire wrote:
Rob Prime wrote:Try changing line 21 to "Point[] pa = new Point[4];" and try again.


I see, so inside of set.toArray() it is doing:

Something like that (this won't compile because of x missing).

on line four, the method has no way to extract the type from it.next and use it, which is why we get the casting error.

Not quite. The exception is not caused by anything inside the method, but after it has returned, because the array is an Object[] (as created at the top), not a Long[]. The trouble is line 1, but you got the reason right.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic