• 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

Casting in array

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

Here is some snippet ,

class A{}
class B extends A{}
class C extends B{}

class Main{
public static void main(String... args){
C [] c = new C[5];
B [] b = c ;
A [] a = c ;
}
}

Here we see that array of type c can be casted to its super class A and B , that is upcasting is valid if array is of type Object .

But this is not valid in case of primitives .

class PrimitiveArray{
public static void main(String... args){
int [] i = new int[4];
long [] l = i ; // compile-time error
short [] s = i ; // Again compile-time error
}
}
In case , array of primitives , upcasting is not valid . What is the reason behind it .
 
Ranch Hand
Posts: 110
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's because your arrays are of different types.
When you write B [] b = c ; it's OK because c and b share the same inheritance tree (C extends B).
But the primitives are not classes: you can't say "int extends long"
 
Ranch Hand
Posts: 117
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Also consider that object references are of the same bit length. It doesn't matter whether they refer to a Universe object or an Ant object.

Casting an array reference that refers to an array object that contains references to objects is like saying "Well, it are object references of type X, but from here on I'll consider them objects of type Y. Nothing basically changes in the nature of the work of getting that object reference at index I".

Naturally, calling them of the type Y while they are actually type X requires the certainty that whatever you do with Y could also be done with X, which is (fortunatly) enforced by the compiler.

Now consider upcasting an array of integers to an array of longs. The array object doesn't change at all, but you _are_ saying that, since you consider the array to be of long values (and long values take up more memory). Let's say you want the fifth long value of the array (for example). If the compiler would allow this (and if somehow figuring out the location of the fifth index was still intact along with a number of other miracles that have to occur) you would ask a 64 bit length chunk of data from a place where only 32 meaningful bits are stored. What do you think can happen?

Next to that, under the hood different instructions are used to load and store the primitives of all types and all kinds of technical problems arise even if you'd cast an array of chars to an array of shorts (16 bit to 16 bit).

I hope this helps (and doesn't add confusion instead ).
[ June 11, 2008: Message edited by: Ronald Schild ]
 
Greenhorn
Posts: 8
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I java array is considered as object, so like object,we can assign child object to parent reference. this is not the case of primitive data type, so it can't possible with primitive data type
 
Ranch Hand
Posts: 320
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I may be jumping in a little hastily but what I feel an urge to say is that there has to be an inheritance relationship to do that. In your case, a C "is a" B, so you can assign a reference to an array of C's to a reference that is declared as an array of B's. A C "is an" A so the same holds true for assigning a reference to an array of C's to a reference declared as an array of A's.

The same can not be said about primitives though. While the compiler widens the values for computational operations, from an object hierarchy perspective an in "is NOT a" long so it will not explicitly assign the references like that without a cast. And, if I am thinking right, you can cast it and get it through the compiler you would get a runtime exception when you ran the program.
 
Madhukar Ojha
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot Gomes , Schild , naphade and Ruth

For sharing your knowledge .

 
Madhukar Ojha
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Schild

I want to mention one thing .
Casting an int[] to long[] is not allowed because of both primitives
have different width .

But Downcasting is safe according this idea .

Because if

int [] i = new int[5] ;
short [] s = i ;

is possible than

with reference s you can store data , because short width has smaller
than int . Hence you are safe . I think it could be allowed .
As far as i think , In this case only return type matters .

What is your view .

 
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
int arrays and short arrays at both objects. In the object hierarchy, they both inherit from the Object class. So, it is *not* possible to cast in either direction, as neither is the subclass or superclass of the other.


BTW, instead of speculating, you could have spent a minute to try it out.

Henry
[ June 13, 2008: Message edited by: Henry Wong ]
 
Ranch Hand
Posts: 64
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Just have a question in the same topic.

ArrayReference casting is allowed, as long there is some inheritance.

Sohn extends Vater. sohnArray and vaterArray are initialized to 0-5.

After the array reverence assignment

vaterArray=sohnArray; //Arrayreferenz-Zuweisung

the values of vaterArray are all 0. Why?


class Vater{
int i=0;
public Vater(){};
public Vater(int j){
i=j;
}
}

class Sohn extends Vater{
int i=0;
public Sohn(){};
public Sohn(int j){
i=j;
}
}

public class ArrayTest{

public static void main(String... args){
Sohn[] sohnArray=new Sohn[5];

for (int i=0;i<sohnArray.length;i++)
sohnArray[i ]=new Sohn(i); //Initialisierung SohnArray
//sohnArray[i].i=i; //geht nicht, null pointer Exception

for (int i=0;i<sohnArray.length;i++)
System.out.print(sohnArray[i].i);//Ausgabe sohnArray
System.out.println();

Vater[] vaterArray=new Vater[5]; //Member werden auf 0 initialisiert

for (int i=0;i<sohnArray.length;i++)
vaterArray[i]=new Vater(i); //Initialisierung vaterArray

for (int i=0;i<vaterArray.length;i++)
System.out.print(vaterArray[i].i);//Ausgabe vaterArray

System.out.println();

vaterArray=sohnArray; //Arrayreferenz-Zuweisung

for (int i=0;i<vaterArray.length;i++)
System.out.print(vaterArray[i].i);//Ausgabe vaterArray (alles = 0)



for (int i=0;i<vaterArray.length;i++)
vaterArray[i].i=sohnArray[i].i; //Kopieren der Werte

System.out.println();
for (int i=0;i<vaterArray.length;i++)
System.out.print(vaterArray[i].i); //Ausgabe

}
}
Output:

01234 //sohnArray initialized
01234 //vaterArray initialized
00000 //after Array Refernce Assignment, vaterArray all i equals 0
01234 //copy values from sohnArray to vaterArray

Has it to do with a shallow copy (thougt this would only happen if there are some objects composited).


 
Henry Wong
author
Posts: 23951
142
jQuery Eclipse IDE Firefox Browser VI Editor C++ Chrome Java Linux Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Has it to do with a shallow copy (thougt this would only happen if there are some objects composited).



No.... The cause of the problem has nothing to do with shallow copy.



If you look at the Sohn class, you will notice that construction of Sohn instances uses the default contructor of the Vater class -- as you didn't use super(int). This means for Sohn objects, the Vater component is always zero, since that is what the default constructor does.

And inheritance doesn't apply to variables. So... when you use the Vater reference on the Sohn object, it will return the i from the Vater portion of the instance, which is set to zero.

Henry
 
Terence Gronowski
Ranch Hand
Posts: 64
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Henry

Many thanks , now its (almost) clear. I rearranged the code, so everybody understands it.

It seems when I create instances of Sohn there are also created new i s which are from Vater portion of Sohn. The i s are given a value 20 and higher for distinction purposes. They have nothing to do with the i s in vaterArray (Values 10 .. 14).

After the assignment the Sohn portion is unreachable, because the reference is of type Vater and sees only the Vater portion in the Son object.

Is this explanation correct?

class Vater{
int i=5;
public Vater(int i){
this.i=i;
}
}

class Sohn extends Vater{
int j=10;
public Sohn(int j){
super(j+20); //call parameter Constructor Vater(int i), +20!
this.j=j;
}
}

public class ArrayTest{

public static void main(String... args){
Vater[] vaterArray=new Vater[5]; //Declaration of vaterArray,
//Constuctor didnt run yet
for (int i=0;i<vaterArray.length;i++)
vaterArray[i]=new Vater(i+10); //Initialisation with parameter
// Constructor Vater(int i)0..4

for (int i=0;i<vaterArray.length;i++)
System.out.print(vaterArray[i].i+" "); //Output vaterArray 10...14
System.out.println("=> vaterArray in Object Vater");

Sohn[] sohnArray=new Sohn[5]; //Declatation of sohnArray,
//Constructor didnt run yet

for (int i=0;i<sohnArray.length;i++)
sohnArray[i]=new Sohn(i); //Constructor of Son
//calls parameter Constructor of
//Vater, Adds 20 to i
//New Vater portions in Son
//are created


for (int i=0;i<sohnArray.length;i++)
System.out.print(sohnArray[i].j+" "); //Output sohnArray.j
System.out.println("=> Sohn portion in Object Sohn");

for (int i=0;i<sohnArray.length;i++)
System.out.print(sohnArray[i].i+" "); //Output Vater portion of Sohn
System.out.println("=> Vater portion in Object Sohn");

vaterArray=sohnArray; //Array Reference Assignment, vaterArray points to
//Vater portion in Son Object

for (int i=0;i<vaterArray.length;i++)
System.out.print(vaterArray[i].i+" ");//Output
System.out.println("=> Vater portion in Object Sohn");

//for (int i=0;i<vaterArray.length;i++)
//System.out.print(vaterArray[i].j+" "); //j is unknown in
//Vater-Part of Sohn
System.out.println("=> Sohn portion not reachable after Assignement");
}
}

/*
Output
10 11 12 13 14 => vaterArray in Object Vater
0 1 2 3 4 => Sohn portion in Object Sohn
20 21 22 23 24 => Vater portion in Object Sohn
20 21 22 23 24 => Vater portion in Object Sohn
=> Sohn portion of Object Sohn is not reachable after Assignement

Hope it is time for a beer

*/
 
Terence Gronowski
Ranch Hand
Posts: 64
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I just have another question of this topic.

The allowed Array Reference Assignments are defined in the JavaLanguageSpecification, Chapter 5.

Among others it is allowed

WIDENING

any ArrayType to Type Object

NAROWING

any ArrayType SC[] to another ArrayType TC[], provided that SC to TC is a narrowing conversion.

I want to construct some practical examples e.g.

First Example (widening conversion):

int[] intArray={1,2,3,4,5};
Object o=intArray; //compiles and runs

Question: What do I make with o, I cannot print o[0], because o is not an array.

Second Example (narrowing conversion):

Object o=0;
int[] intArray=(int[])o; //compiles, runtime error java.lang.Integer
//cannot be cast to [I


Why does it compile? It from the JavaLanguageSpecification it should not be allowed.

Does somone have some more reasonable examples for this topic??






 
Ronald Schild
Ranch Hand
Posts: 117
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Question: What do I make with o, I cannot print o[0], because o is not an array.



You didn't change the actual array object, but with the reference o you state to see it as an instance of class Object. You can use methods defined in that class.

Object o=0;
int[] intArray=(int[])o; //compiles, runtime error java.lang.Integer
//cannot be cast to [I


Why does it compile? It from the JavaLanguageSpecification it should not be allowed.



All arrays are objects. So this is a valid downcast. The compiler can not guarantee that o is in fact an array, this is why the explicit cast is required. I believe the following from the JLS applies:

From any reference type S to any reference type T, provided that S is a proper supertype (�4.10) of T. (An important special case is that there is a narrowing conversion from the class type Object to any other reference type.)

 
Sheriff
Posts: 67748
173
Mac Mac OS X IntelliJ IDE jQuery TypeScript Java iOS
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
"Terence", please check your private messages for an important administrative matter.
 
It sure was nice of your sister to lend us her car. Let's show our appreciation by sharing this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic