why this cast won't work?

J

Jack

the following compiles okay, but throws a ClassCastException at
runtime. Why?



import java.net.*;

public class CastSocket extends Socket {

public static void main(String[] args) {
try {
ServerSocket server = new ServerSocket(80);
CastSocket cs = (CastSocket)server.accept();
} catch (Exception e) {
System.out.println(e);
}
}

}
 
P

praveen

The accept method in ServerSocket class returns a new object of class
Socket, which in this case, is the super class of class CastSocket.
You are trying to cast a superclass object into its subclass, which is
not possible.

Downcasting a superclass reference to its subclass object is valid ONLY
if the superclass reference is actully pointing to an object of its
subclass.
e.g.
class A {}
class B extends A {}
....
A a1 = new A();
B b1 = (B)a1; -> invalid, since no object of B was created.
A a2 = new B();
B b2 = (B)a2; -> valid, because a2 is pointing to a B object.
 
J

Jack

Downcasting a superclass reference to its subclass object

Oh, I see now. Thanks. Casting never actually changes any object, it
only can change the type of the *reference* to that object. So, if we
speak of casting objects, that is essentially incorrect.

What does the reference to an object look like anyway? How is it laid
out in memory? There must be a field for name, for type, and a pointer
to the actual object in memory. What else? Is there any way, using any
tool, that I can see this myself? Thanks.
 
R

Roedy Green

ServerSocket server = new ServerSocket(80);
CastSocket cs = (CastSocket)server.accept();

Whenever you are puzzled by a run time cast exception you can write
some code like this:

Object cs = server.accept();
System.out.println( cs.getClass() );

Casting the rereference to what you are actually getting will work, an
interface it supports, or a superclass of it, but nothing else.

You can't change it into anything else with a reference cast. You
can't cast it into something it is not already.

You can with (int) somelong convert a long to an int, however.
 
C

Chris Smith

Jack said:
Oh, I see now. Thanks. Casting never actually changes any object, it
only can change the type of the *reference* to that object. So, if we
speak of casting objects, that is essentially incorrect.

Yes, precisely!
What does the reference to an object look like anyway? How is it laid
out in memory?

This is technically unspecified. In practice, it's pretty much always
just a memory address; 32 or 64 bits, depending on the JVM platform.
There must be a field for name, for type, and a pointer
to the actual object in memory. What else?

Nope. The name is either:

1. Only significant at compile time, if it's a local variable, OR
2. If it's a field, associated with the containing class, OR
3. Non-existent anywhere, if it's an intermediate result.

So there isn't a name as part of the reference itself. In other words,
if I write:

class Test
{
private void a(Test p1)
{
}

public static void main(String[] args)
{
Test t = new Test();
a(t);
}
}

There is NOTHING that I could do to the parameter p1, at runtime, that
would tell me that the reference was originally called t. In fact, if
you compile without debug information, then neither "p1" nor "t" will
appear in the class file.

Types are similar. They are used by the compiler to check type safety.
By the time the code is written out to the class file, there is no sign
of the type you declared for that reference.

So, only the memory address is actually stored.
Is there any way, using any
tool, that I can see this myself?

Not easily. You could cause a core dump in native code for a Java
process in UNIX, but you've have a heck of a time tracing everything
through JIT'ed machine code to figure out what's happening.

You could agree to the SCSL and download source code for the JDK, as
well. That might be easier than the first option, but it's definitely
non-trivial to find the relevant code.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
R

Roedy Green

This is technically unspecified. In practice, it's pretty much always
just a memory address; 32 or 64 bits, depending on the JVM platform.

In some of the older JVMS it was a handle, i.e. a slot number in a
table that pointed to where the object really was. That way the
object could be moved without having to adjust all the pointers to it.

That was the way the original Mac did memory allocation in Pascal.
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top