question about casting and inheritance

  • Thread starter marc.at.compass
  • Start date
M

marc.at.compass

Hello,
I'm preparing for Java 7 OCA exam. I have a q about casting..
I learned you can cast a variable of a class to another object only if there's a hierarchical relation between the variable's class _and_ the object'sclass you cast to. And also, the varibla should point to an object og the class you're casting to or you get a ClassCastException during runtime.
So I made up this example:

class A {
String uniqueMethodForA(){
return ("uniqueMethodForA");
}
}

class B extends A {
String uniqueMethodForB(){
return ("uniqueMethodForB");
}
}

public class LearnJava{
public static void main(String[] args) throws Exception {
LearnJava LJ = new LearnJava();
A a = new A();
B b = new B();
System.out.println(a.uniqueMethodForA());
System.out.println(b.uniqueMethodForB());
a=b;
b=(B)a;
System.out.println("=============");
System.out.println(a.uniqueMethodForA());
System.out.println(b.uniqueMethodForB());
}
}
outputs:
uniqueMethodForA
uniqueMethodForB
=============
uniqueMethodForA
uniqueMethodForB

As you see variable a points to an instance of A and not to (an instance of) B. I effectively say "treat a as if it is b". I can even call a method onb that is unique for B. But a didn't point to an instance of B in the first place at all!
Why is it the line b=(B)a; doesn't give me a ClassCastException during runtime?
 
E

Eric Sosman

Hello,
I'm preparing for Java 7 OCA exam. I have a q about casting..
I learned you can cast a variable of a class to another object only if there's a hierarchical relation between the variable's class _and_ the object's class you cast to. And also, the varibla should point to an object og the class you're casting to or you get a ClassCastException during runtime.
So I made up this example:

class A {
String uniqueMethodForA(){
return ("uniqueMethodForA");
}
}

class B extends A {
String uniqueMethodForB(){
return ("uniqueMethodForB");
}
}

public class LearnJava{
public static void main(String[] args) throws Exception {
LearnJava LJ = new LearnJava();
A a = new A();
B b = new B();
System.out.println(a.uniqueMethodForA());
System.out.println(b.uniqueMethodForB());
a=b;
b=(B)a;
System.out.println("=============");
System.out.println(a.uniqueMethodForA());
System.out.println(b.uniqueMethodForB());
}
}
outputs:
uniqueMethodForA
uniqueMethodForB
=============
uniqueMethodForA
uniqueMethodForB

As you see variable a points to an instance of A and not to (an instance of) B. I effectively say "treat a as if it is b". I can even call a method on b that is unique for B. But a didn't point to an instance of B in the first place at all!
Why is it the line b=(B)a; doesn't give me a ClassCastException during runtime?

Because "a" refers to the object originally pointed to by "b",
that is, to the object created by "new B()". That object is a B
object, so converting its A-type reference "a" to a B-type reference
is no problem. For contrast, try

A a = new A();
B b = new B();
...
A a2 = b;
B b2 = (B) a; // ClassCastException here
 
M

markspace

a=b;
b=(B)a;
Why is it the line b=(B)a; doesn't give me a ClassCastException during runtime?

Because the line above assigns 'b' to 'a'. It's actually the only
interesting thing inside the program. The second line with the cast is
a tautology: it casts 'b' to a 'B'.

A more explicit naming scheme for your variables would help a lot to
understand this.
 
R

Ricardo Palomaes

El 09/01/14 19:48, (e-mail address removed) escribió:
As you see variable a points to an instance of A and not to (an
instance of) B.


In fact, variable "a" is a reference to an object of class A. Since
class B extends A, an object of class B is also an object of class A
(it is "just a more specific type of A"). Thus, when you do:

a = b;

a is referencing the same object than b, ie., an object of class B.
While accessing that object from "a", it only can behave as a class A
object, and you couldn't do a.uniqueMethodForB(). However, as soon as
you access the object from b again, you can access again the methods
exclusive of a class B object. Note that, during this sequence:

a = b;
b = (B) a;

the object itself has not been touched nor modified at all; you only
have modified the references "a" and "b" (and "b" has been modified
only to leave exactly as it was).

I effectively say "treat a as if it is b". I can
even call a method on b that is unique for B. But a didn't point to
an instance of B in the first place at all!


Yes, it did. At least, since you did a = b. :)


Why is it the line b=(B)a; doesn't give me a ClassCastException
during runtime?


Because a holds a reference to a class A object that happens also to
be a class B object, so it is not wrong to reference as such.

HTH
 
A

Arved Sandstrom

On 01/10/2014 07:04 AM, Patricia Shanahan wrote:
[SNIP]>
There are two ways of thinking about Java that, in combination, make
this type of issue very simple and clear:

1. Distinguish between the type of an expression and the class of an
object.

2. Every non-null reference expression is a pointer to an object whose
class is matches the expression's type, or extends it, or implements it.

Every expression has a type that is determined at compile time. For a
variable or parameter the type is directly declared. The type of
variable a is A, and the type of variable b is B. Other expressions have
types that can be determined from the nature of the expression and the
types of its operands. The type of "(B)a" is B.

Each object has a class that is determined by how the object is created,
through clone() or new. The class of the object created by "new B()" is
B, and remains B regardless of what variables or expressions point to it.

Applying this thinking to the code above, "a=b" assigns to variable a
the value of b, which is a pointer to an object of class B. Because B
extends A, the compiler knows that variable b either is null or is a
pointer to an object that variable a is allowed to point to, so no cast
is needed.

"b=a" would be rejected at compile time because variable a can point to
objects that variable b cannot point to.

"b=(B)a" is accepted by the compiler because variable a can point to an
object that variable b can also point to. It would cause a
ClassCastException at run time if, in fact, variable a pointed to an
object variable b cannot. It points to an object that was created by
"new B()", an object whose class is B, so the cast is valid.

Patricia

"Simple and clear" to a person that knows OO quite well already,
Patricia. :)

AHS
 
M

marc.at.compass

Thanks all for the replies! Very informative. I'm a further on the path of casting and definitely will follow up on the link about casting given.

thanks again!

Marc
 
S

Stefan Ram

Ricardo Palomaes said:
class B extends A, an object of class B is also an object of class A

I try to say »/instance/ of class A« in such a case.

public class Main
{ public static void main( final java.lang.String[] args )
{ class A{}; final class B extends A{}; final B b = new B();
@java.lang.SuppressWarnings( "rawtypes" )final java.lang.Class bc = b.getClass();
@java.lang.SuppressWarnings( "rawtypes" )final java.lang.Class ac = A.class;
java.lang.System.out.println( bc == ac ); /* false */
java.lang.System.out.println( b instanceof A ); /* true */ }}
 
R

Ricardo Palomares

El 11/01/14 18:40, Stefan Ram escribió:
I try to say »/instance/ of class A« in such a case.


I was about to change it before sending it, indeed, :) but I thought
it would be clearer to the OP to see "object".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top