• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

List & toArray()

 
Ranch Hand
Posts: 127
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I am reading Jeanne's OCP 1Z0-809 Oracle Certified Professional Java SE 8 Programmer II book.

I ran into a problem on Chapter 3, page 105. I tested the code shown in the book. But it gives me ClassCastException.

Is  down casting allow here? String[] array2 = (String[]) list.toArray(); This returns an Object array.
I know that String[] array2 = list.toArray(new String[0]) works by specifying the String[] array as a parameter for toArray() method. And it will give you a String array.






The error is:


Exception in thread "main" java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.lang.String; ([Ljava.lang.Object; and [Ljava.lang.String; are in module java.base of loader 'bootstrap')
at com.packt.learnjava.ch01_start.PrimitiveTypes.main

Here is what I found.

Object[] name = {"Hello"};
String[] result = (String []) name; // Error


For non-array, this works:
Object name = "Hello";
String result = (String) name; // OK


If I change the array creation to new. The code work. See below examples. I don't know why?

Example 1: This is the original code that didn't work.
Casting Object array to String array. 


------------------------------------------------------------------------------------------
Example 2: working code
This time I changed the way I declare the String array to use "new".
Casting Object array to String array.

------------------------------------------------------------------------------------
Example 3: working code

This time I cast String array to Object array.

 
Bartender
Posts: 390
47
Firefox Browser MySQL Database Java Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
From the Java Language Specification 10.2:

If an array variable v has type A[] , where A is a reference type, then v can hold
a reference to an instance of any array type B[] , provided B can be assigned to A
(§5.2). This may result in a run-time exception on a later assignment; see §10.5
for a discussion.



The issue is, as you pointed out, that your objectArray variable holds a reference to an object of the Object[] type. An Object[] object cannot be assigned to a variable of type String[], hence your exception. When you create a new String array, however, it is a String[] object. A variable of type Object[] can hold its reference, because String is assignable to Object. Casting the reference type to String[] is fine, because that is what it is. There is no problem assigning a String[] object to a variable of type String[], obviously   .

It is the same with your last example. There is no problem assigning an String[] object to a variable of type Object[], since String is assignable to Object
 
Marshal
Posts: 79177
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
JJ is right, but there is more.
You are looking at the runtime type of the elements in your example 1. Because you used a plain simple array initialiser, the runtime type of the array is the same as its declared type. As JJ said, since Strings are Objects, they can be assigned to elements of an Object[]. But the array's runtime type is Object[] (=[Ljava.lang.Object;), so it cannot be cast to any other type of array.
In example 2, you are assigning a String[] to an Object[] reference.
In example 3, you are using a widening conversion. Remember that widening conversions of reference types have no effect on the object cast, but always execute without exceptions. Widening reference conversions are there “for entertainment purposes only”; they have no real effect on anything.
Did you read the documentation for List#toArray()? Did you see what its return type is? Did you see the strange design of its overloaded brother? For an exercise, see if you can find a version of that overloaded method for Java1.2 or Java1.3 or Java1.4 and see how it differs from the current version.
 
Jesse Duncan
Bartender
Posts: 390
47
Firefox Browser MySQL Database Java Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:
Did you read the documentation for List#toArray()? Did you see what its return type is? Did you see the strange design of its overloaded brother? For an exercise, see if you can find a version of that overloaded method for Java1.2 or Java1.3 or Java1.4 and see how it differs from the current version.


Henry noted that toArray(new String[0]) returns a String[], and that toArray() returns an Object[]

Is  down casting allow here? String[] array2 = (String[]) list.toArray(); This returns an Object array.
I know that String[] array2 = list.toArray(new String[0]) works by specifying the String[] array as a parameter for toArray() method. And it will give you a String array.


I think the root of the confusion lies in what the cast actually does, in widening vs. narrowing contexts.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jj Roberts wrote:. . . Henry noted that toArray(new String[0]) returns a String[] . . . .

My apologies; you obviously did look at the documentation.
 
Campbell Ritchie
Marshal
Posts: 79177
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have found a JDK1.4.2 documentation link. This is what it says about List#toArray:-

toArray

public Object[] toArray()

   Returns an array containing all of the elements in this list in proper sequence. Obeys the general contract of the Collection.toArray method.

   Specified by:
       toArray in interface Collection

   Returns:
       an array containing all of the elements in this list in proper sequence.
   See Also:
       Arrays.asList(Object[])



toArray

public Object[] toArray(Object[] a)

   Returns an array containing all of the elements in this list in proper sequence; the runtime type of the returned array is that of the specified array. Obeys the general contract of the Collection.toArray(Object[]) method.

   Specified by:
       toArray in interface Collection

   Parameters:
       a - the array into which the elements of this list are to be stored, if it is big enough; otherwise, a new array of the same runtime type is allocated for this purpose.
   Returns:
       an array containing the elements of this list.
   Throws:
       ArrayStoreException - if the runtime type of the specified array is not a supertype of the runtime type of every element in this list.
       NullPointerException - if the specified array is null.

Some of the details in the Java14 version are to be found in the JDK1.4 Collection#toArray page.
 
henry leu
Ranch Hand
Posts: 127
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for all your explanations!

Problem solved!
 
reply
    Bookmark Topic Watch Topic
  • New Topic