aspose file tools*
The moose likes Java in General and the fly likes Cast Object back to its original type Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "Cast Object back to its original type" Watch "Cast Object back to its original type" New topic
Author

Cast Object back to its original type

Andy Nimmo
Greenhorn

Joined: Mar 30, 2003
Posts: 14
I have a method to which I expect have one of two possible Classes sent to at any given time.
I could just create two forms of this method however this is something I come across on a regular basis and have always wanted to know if it is possible to do this.
I have a class which I cast to type Object then pass it to a method call. In the method body I want to cast this object back to it's previous type.
For example:
ContactsList -> Object -> saveToFile( theObject )
theObject -> ContactsList
Hope this makes sense.
Can anyone help? I've had a look at Java Reflections but I'm having a bad day and I'm unable to decipher what's in there and apply it to my situation.
All help is greatly appreciated.
Cheers,
Andy.
*****************************************************
Here I Stand, Alone, Left To Face The Coming Darkness
Bring it on!!
*****************************************************
[ February 19, 2004: Message edited by: Andy Nimmo ]
Stan James
(instanceof Sidekick)
Ranch Hand

Joined: Jan 29, 2003
Posts: 8791
One way to solve this is to make your two possible classes "extend" the same base class or "implement" a common interface. Then if you can call methods defined on the base class to work on them, you won't ever have to know which one you get.

Now if somebody calls MyClass with either a Cat or Dog we'll get the correct sound. Holler if that didn't make sense.
But what if you really can't make Cat & Dog implement the same interface? Maybe you bought one from Acme and the other from Best? You do something more like this:

We have to find out exactly what we're dealing with, cast it to the real class and call a method. Note that acme and best didn't agree on having a speak() method. With Dog I made a local variable for clarity. With Cat I cast and called the method all in one line. If that's too many parens in one line for your eyes, do it the other way.
For your original question, you were just missing instanceof. But the polymorphic solution using extends or implements makes life a lot easier!
[ February 19, 2004: Message edited by: Stan James ]

A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Wayne L Johnson
Ranch Hand

Joined: Sep 03, 2003
Posts: 399
You can use the "instanceof" operator to determine the actual class of an object instance. For example, if your method was expecting either a "String" or a "java.util.Date", you could do something like:

However it's much better to simply use overloading:

If there is some common code, you can factor that out into a third method, make it "private", and invoke it from the two other methods.
Later if you need to add a third object type, simply create another method.
I think this way is easier to read, easier to maintain, and allows you to catch things at compile time rather than at run time. And there is no unnecessary class casting to do.
Andy Nimmo
Greenhorn

Joined: Mar 30, 2003
Posts: 14
Thanks guys.
Both are kind of what I was expecting although I'd overlooked the instanceOf method call.
The reason I asked this question wasn't simply down to my example situation as I have in the past created some generic methods which could accept a number of different objects and act accordingly. I just hate long windedness and do my best to make things clear aond concise, sometimes to overload a method can result in a large quantity of highly similar code which cant be refactored into a second method call without resulting in yet more code.
I have what I need now.
Cheers again,
Andy.
Sajee Joseph
Ranch Hand

Joined: Jan 17, 2001
Posts: 200
Hello,
Please remember that there is a catch in instanceOf operator.
This operator returs true when u use it against a parent class too.
Consider the following code:

class AUpper
{
}
class ALower extends AUpper
{
}
class TestInstanceOf
{
public static void main(String[] a)
{
ALower n = new ALower();
if(n instanceof AUpper)
System.out.println("AUpper");
if(n instanceof ALower)
System.out.println("ALower");

}
}
This will print the following:
AUpper
ALower
Cheers
_saj
sever oon
Ranch Hand

Joined: Feb 08, 2004
Posts: 268
Augh! Don't use instanceof!!!
Or at least, before you do, I highly recommend you read this article over at Object Mentor...if the entire thing is too long-winded for ya, do a search for "dynamic polymorphism" and just read that page or two.
The problem you are grappling with is a common one, but to give a proper approach I'd have to know more about it. I understand you have some method, foo(), to which you are passing two different types. Does this method treat both of these types in the exact same way, or does it treat them differently? This makes a world of difference.
If you execute the same logic on both types, then you should think about the applicability of that logic to other types as well. If that logic can be applied to all objects, no matter what type they are, then go ahead and have it take any Object. (Example: if it returns "hash code:" followed by the hash code of the object, this indeed can be run on any object at all.)
If it only makes sense to pass this method certain kinds of objects, then maybe you want to think about creating an interface for those kinds of objects and have them all implement it. For example, I wrote a system that could chain together certain objects in any kind of order. All of those objects implemented the Chainable interface. At first, this interface didn't specify any behaviors at all, it was just a tagging interface that allowed me to treat all chainable types as...well, Chainable. Later, when we added other requirements to the system it became necessary to have chainable objects all implement a few simple behaviors, so I added those behaviors to the interface and implemented them throughout.
Great--but what if the situation you're talking about treats these different types differently? First of all, I'd question the design. If you're treating two different types completely different, is it possible that you should have two completely different methods? However, if conceptually you are doing the same thing, it's just the process that differs between the two types, then it's ok.
Example time. If you have a method start() that starts a Car object (S.o.println("vroom")) and an Altercation object (S.o.println("You're stupid")), these are two totally unrelated things that happen to use the same verb. They should have two completely different methods with less ambiguous names than "start". On the other hand, if you're trying to calculate the perimeter of a Circle object (return 2*Math.PI*r) and a Rectangle object (return 2*width + 2*height), this is conceptually the same thing.
However, in the latter case, with the rectangle and the circle, you should implement overloaded methods, calcPerimeter(Circle) and calcPerimeter(Rectangle). This is totally appropriate.
Another thing to consider...whenever I find myself implementing overloaded methods, I always check to make sure I've put this functionality in the correct place. In the example above of calculating the perimeter of shapes, I might run into this decision while implementing a Shape class (a final class that is a toolkit for different shapes) with a static method calcPerimeter(). I would stop, though, and wonder if maybe instead I should do away with the toolkit approach--after all, that's the procedural approach, not object-oriented. Instead, I'd prefer to make Shape an abstract base class with an abstract method, getPerimeter(), and have Circle and Rectangle extend it, each providing their own implementation for the method.
If you go this way, then you should consider whether Shape should be an abstract class or an interface. In this application, you might want to mandate that all Shapes track the number of sides they have (a circle one, a rectangle 4, etc). This code could easily be provided at the base class level b/c it's the same for every possible shape:

Or, you might prefer to make Shape an interface if being a shape isn't the "main job" of the subclasses that would extend it. (For example, if it's more important to the design of your app that they extend another class, like DrawableWidget, that provides a lot of concrete functionality, you'd want to extend that and implement a Shape interface instead.)
For a good discussion on abstraction and stability, check out this article over at Object Mentor too.
sev
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Cast Object back to its original type
 
Similar Threads
Generics compendium
a question on parameter passing
Need to resolve ClassCastException
contains() & equals()!
generic casting with object.getClass() ?