Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

dynamic casting 1

Status
Not open for further replies.

RogerFGay

Programmer
Jun 22, 2001
49
0
0
SE
It seems so obvious. I send various types of objects through an object stream. When they get to the other side, they are read as Object obj = in.readObject() : type Object. I can easily get the name of the original class type via obj.getClass().getName()

Now what I want is a very simple way of casting back to the original class type so that I can use overloaded handlers - i.e. one handler for each type that this application may receive. I've tried all day, but still can't find anything that works. Here's one thing I've tried.

try {
process2Input(obj.getClass().cast(Class.forName(rtm.getClass().getName())));
} catch (ClassNotFoundException e) {
}

As with other things, it still thinks it's Object class rather than its original class, which is given by getName()

 
I've wondered if that was possible too, but so far I haven't needed to do it.
 
It's non-essential. But in my opinion, it would be really nice. I want it.
 
Java 1.5 and 1.6 have a cast() method. The Class can be obtained using the forName() method, and the name of original class can be retrieved using getClass().getName().

But it doesn't give the result that seems logical to me.

Class.forName(obj.getClass().getName()).cast(obj);

always returns an object of type Object. What sense does the cast() method make?
 
Have you verified that the objects you are receiving on the output of the object stream actually return their original classnames using obj.getClass().getName() ?


-V
 
Dynammic casts are simply impossible.
Let's assume for a second it would:
Code:
<X> x = (magic dynamic cast) o;
Now what do we do with that x?
It might be anything - a JFrame, a Timestamp, a Matcher, ... we don't know.
So what can we do with it?

don't visit my homepage:
 
Stefan - That's where I was leaning, but I am not nearly familiar enough with java to come out and say it. Thanks for clearing things up!

Alex

I don't do any programming whatsoever

Ignorance of certain subjects is a great part of wisdom
 
stefanwagner said:
Dynammic casts are simply impossible.
Why? I've never used it in Java, but in C++ it works like this:
Code:
void SomeFunction( Parent*  parent )
{
   Child* kid = dynamic_cast<Child*>( parent );

   if ( kid == NULL )
   {
      cout << "Parent pointer is not a Child pointer!";
   }
}

void SomeOtherFunction( Parent&  parent )
{
   try
   {
      Child& kid = dynamic_cast<Child&>( parent );
      ...
   }
   catch( bad_cast&  e )
   {
      cout << "Parent reference is not a Child reference!";
   }
}
If the cast fails it either returns NULL or throws an exception.
 
I'm not used to dynamic casts in c++.

You show us code where a Parent might get casted to a Child.
That's no problem in Java:
Code:
 void someOtherFunction (Parent parent)
{
	if (parent instanceof Child) 
	{
		Child kid = (Child) parent;
		kid.doSomething ();
	}
	else 
	{
		System.out.println ("Parent reference is not a Child reference!");
	}
}
But as I understood the question, the idea is not to know at all what kind of object is passed.

'dynamic cast' might be an very inappropriate expression, at least it's not what c++ - users expect by it.

don't visit my homepage:
 
Right now, I have code to handle three different input types, all of which orignially come through ObjectInputStream as type Object. The original object type can be retrieved from the input Object obj, with obj.getClass().getName() or instanceof.

Objects are currently being cast back to their original type by a series of if statements of the form:

Type1 type1Obj = null;
Type2 .....

if (obj instanceof Type1) {
type1Obj = (Type1)obj:
} else if (obj instanceof Type2) {
type1Obj = (Type2)obj:
.... etc.


The new cast() method can be used to write the statements this way:

if (obj instanceof Type1) {
type1Obj = Type1.class.cast(obj):
} else if ( .....

I'd like to do something more along the lines of what cpjust suggests, but I'm not sure it can be done in Java. It would be nice if I could just call the processing method and let overloading determine which variation is the right one. But that means;

processInputObject ((cast to instanceof type)obj);

public void processInputObject (Type1 type1Obj) {
... do stuff ...
}
public void processInputObject (Type2 type2Obj) {
... do different stuff ...
}

... etc.

 
I'd just treat the deserialiser as an implementation of the Factory pattern; it 'creates' instances (in this case deserialises them from a stream) and keeps the ugly details of this (type checking and casts) encapsulated within it.

Tim
 
Do you mean add get and set methods to the object being transported? I've been trying to avoid that. Much as I'd like them, they add to the size of data object being transferred.
 
Eh?

I'm talking about the class you use to perform the deserialization. And all I'm advocating, I suppose, is that you live with the lack of dynamic casting but keep all the typechecking inside this class, just like it was an instance factory.

By the way, I think that adding methods and code does not make an instance of a class, or it's serialized version, any bigger as far as I know. These are part of the Class, not the instance. Maybe someone could confirm this for me, in case I'm spouting nonsense.

Tim
 
Your thoughts about the size of an instance have been confirmed. I'm still learning ... and your way of putting it made the point even clearer than before. Makes sense - the intance only needs ... etc. Thanks for that comment!

Type checking is currently done in the class where the objects are read in. It's such a high level thing in Java. I'm using in.readObject() and think that's actually doing the deserialization, right?

Problem is that's happening in a run() method of a thread. The code in the method is getting too complex for my comfort. I think it makes maintenance more difficult - i.e. especially for others who come after me and try to understand what I've written. If I can bury some of the detailed logic and keep the logic simpler and at the same higher level in the run() method, I think it would help.

 
Your are correct in saying that the readObject() method does the deserialization.

Tim
 
First of all, there are no pointer in Java (luckily).

Maybe you can think on having the same method name admiting three different types of objects, that can be done.

You could use instanceof to determine the type and, after cast, call the proper method.

Cheers,
Dian
 
Dian - That's exactly what I do now. See post 6 Aug 07 23:49

 
Diancecht said:
First of all, there are no pointer in Java (luckily).
I don't see much difference between C pointers and Java references. They can both have null values, and they both hold copies of addresses/handles... The only real difference I see is that Java references don't represent the physical memory address of objects and can't be treated as integers.
I wonder why Java throws NullPointerException? You'd think it should be NullReferenceException. ;-)
 
Would you mind taking on another basic question while we're here?

I'm trying to store an object (it's a SOAPMessage object, but I don't think that matters) for later use. I'm having a problem with it - I think. The still might be something else, but as a friend said, I tend to learn languages by going straight to the fun part and skipping over the basics. You caught me on understanding instances, confirming his view.

Anyway - the class that starts the whole system initiates a storage class:

MyStorage myStorage = new MyStorage();

The MyStorage class has a static variable:

static SOAPMessage smPrototype = null;

What I'm trying to do is construct the prototype only once. When the CreateSOAPMessage class is instantiatiated, the constructor checks to see

MyStorage myStorage = new MyStorage();
if (myStorage.smPrototype == null)

If it is null, the prototype is built and stored:

SOAPMessage message = (the SOAPMessage that's created);
MyStorage myStorage.smPrototype = message.

If myStorage.smPrototype is not null, then

message = myStorage.smPrototype;

Do you see any flaws in that? It actually seems to be working, although I've probably side-tracked myself too much with trial and error. Now that I think about it, I probably could do a better job of testing. I only went so far as to print out whether it's null or not. That gives the expected result. I haven't tried to print out smPrototype if it's not null. But at least now that I've typed in this long message - does what I'm doing look ok?

 
You should probably make your static (and non-static for that matter) members private, and just provide Set()/Get() methods for them.

If I'm understanding correctly, something like this might work:
Code:
static private SOAPMessage smPrototype = null;

public static boolean SetSOAPMessage( SOAPMessage  msg )
{
  if ( smPrototype == null )
  {
    smPrototype = msg;
    return true;
  }

  return false;
}

public static SOAPMessage GetSOAPMessage()
{
  return smPrototype;
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top