Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 185
  • Last Modified:

Calling all OO gurus

Can I generate a type cast given only a string containing a class name.

eg if I want to do

TypeA anA = (TypeA)anObjectInputStream.readObject()

can I do this given
String class_name = "TypeA"

I tried
anA = (Class.forName(class_name))anObjectInputStream.readObject()
but that didn't work, strangely!

Any suggestions?
Regards,

Maddy.
0
maddy051398
Asked:
maddy051398
  • 7
  • 2
  • 2
  • +3
1 Solution
 
dryangCommented:


   eg if I want to do

>>   TypeA anA = (TypeA)anObjectInputStream.readObject()

This is OK

>>   can I do this given
>>  String class_name = "TypeA"

Nope! you will just get a String Object, class_name with the value "TypeA"

>>   I tried
>>  anA = (Class.forName(class_name))anObjectInputStream.readObject()
>>   but that didn't work, strangely!

Not strange at all.
1) class_name is a String Object
2) Class.forName is not the same as TypeA - unless Class.forName has the capability to take in a String object and use the String Object value to change its class type (which I doubt it can do)

therefore you are still stuck with
 TypeA anA = (TypeA)anObjectInputStream.readObject()
to do your casting

any futhur questions, just post it here ok?
0
 
maddy051398Author Commented:
Hi,

>> unless Class.forName has the capability to take in a String object and use the String Object value to change its class type (which I doubt it can do)

This was the question I intended! Can I convert a String value to something the compiler will accept as a casting expression.  Not necessarily using Class.forName, that was just the first thing I tried.

So.. how can I put something in a cast expression that isn't a class name?

Regards,

Maddy.
0
 
imladrisCommented:
I don't think that's possible. However, if you explained what you are attempting to accomplish, someone may be able to suggest an alternative that will work.

0
Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
maddy051398Author Commented:
Hi again,

I've just tried to describe the problem without boring you and have given up, suffice to say I've found a way to do what I wanted.

'Simply' put, say I have a base class called Message and a Transmitter class that could receive Message objects - by calling Transmitter.Receive(Message m) - then I wanted to be able to receive all sorts of objects derived from Message without the Transmitter class knowing what they all were.

However ObjectInputStream.readObject(), which I was calling in Transmitter.Receive() needs you to cast to the type you want to receive.

So I got Transmitter.Receive()to call m.GetFrom(stream), implemented in each class derived from Message, passing the ObjectInputStream.  These methods could call stream.readObject()and cast the result to their own types, which they of course know about.

I hope that sounds useful and/or explains my problem.

Regards,

Maddy.
0
 
dryangCommented:
hi maddy,
I see the light now. Good luck to your programming  :)
0
 
maddy051398Author Commented:
Hi,

amazing, I managed to explain it!! Now I have the slight problem of not being able to delete this question now I don't need an answer!
Regards,
Maddy.

0
 
ronaldyangCommented:
Here's an answer!  Accept me please!
0
 
maddy051398Author Commented:
But I need the 100 points for something useful, probably!
0
 
shchukaCommented:
Yes, this is possible.  I've used it before.  The limitation is though is that you need to know exactly what types of parameters the constructor of that class is using.

Let's assume for simplicity that the constructor for class TypeA has no parameters.
Then you can do this nighty trick:

TypeA var = (TypeA)Class.forName("TypeA").getConstructor(null).newInstance(null);

Of course, you need to catch the ClassNotFound exception.

Suppose now that your constructor has one parameter of type string and one parameter of type int[].  Then you'll do this:

Class p1 = Class.forName("String");    //or java.lang.String - I don't remember
Class p2 = Class.forNamr("int[]");

Class[] p = {p1,p2};

String s1 = "hello there";
int[] s2 = {1,2,3,4,5};

Object[] s = {s1,s2};

TypeA var = (TypeA)Class.forName("TypeA").getConstructor(p).newInstance(s);

Again, you need to catch the ClassNotFound exception
0
 
maddy051398Author Commented:
Hi,

In the line...
TypeA var = (TypeA)Class.forName("TypeA").getConstructor(null).newInstance(null);

you've got a cast to TypeA.  This is the bit I need(ed) to avoid.  Say I only know about an interface eg 'AnInterface' that 'TypeA' implements (this stuff is in a separate class that knows nothing about the actual types, only about 'AnInterface' objects)

I want(ed) to do...

AnInterface x = (TypeA)anObjectInputStream.readObject()

but without knowing the type of the derived class.

I guess there's no way to do a cast without having the actual Class name to cast to directly in the code.

So I did...

theMethod ( AnInterface x )
{
   // get the object input stream
   ...

   x.getFrom ( anObjectInputStream ) ;
}

where getFrom() is implemented in class TypeA and knows what to cast the return value of readObject() to.

Regards,

Maddy.
0
 
shchukaCommented:
When you're doing the cast, you don't need to have the class name in the cast type.
Suppose you have something like this:

public interface MyInterface;
public class MyClass implements MyInterface;

Object obj;

Then you can do something like this:
MyInterface mi = (MyInterface)obj;

This along with my previous answer should give you what you need.
0
 
maddy051398Author Commented:
Casting to the base Interface class means ObjectInputStream.readObject() doesn't get the correct (derived) object data from the stream.

Maddy
0
 
thresholdCommented:
I have create this sample for you:
public static void main(String args[]) {
      File file = new File("c:\\temp\\vector.test");
      try {
            ObjectOutputStream os=new ObjectOutputStream(new FileOutputStream(file));
            os.writeObject(new java.util.Vector());
            os.close();

            ObjectInputStream is=new ObjectInputStream(new FileInputStream(file));
            Object obj=is.readObject();
            String name=obj.getClass().getName();
            is.close();
            System.out.println(name);
      } catch (Exception e) {
            System.out.println(e);
      }            
}

The Output is "java.util.Vector".
Although I use "Object obj=is.readObject()", I can get the original class name 'java.util.Vector' from it.
I know you try to invoke any methods or any fields from Objects of any Class.
But with the restriction of Java Language, It's very hard to code it, because the Class type is difined in run-time!

We hope we can do that:
         anA = (Class.forName(class_name))anObjectInputStream.readObject();
         anA.methodA();
It can't be compiled, because the compiler can't know the methodA() is legal or not.

If your serialized Object have a common super Class or Interface, you can invoke the common methods of them.
        MyInterface obj= (MyInterface) anObjectInputStream.readObject();
Of cause, the better code should be:
        Object obj= anObjectInputStream.readObject();
        if (!(obj instanceof MyInterface)) throw new MyException;
        MyInterface myobj=(MyInterface)obj;
If they have no common super Class or Interface, your Object will be useless for programs that invoke them.
If we don't know what methods supported by this object, how do we use it?
Why the INVOKER has to invoke a method of a object? The INVOKER have to know what the method does/means.

Maybe you want to create an Object Database for Java, you need to store/use the object with the maximum flexibility.
And maybe the Interface name will need to be defined in run-time... Here is my proposal:
1. To check/view the Class/Field/Method name of arbitrary object, we should use the java.lang.reflect.* package.
2. To invoke the Methods of arbitrary object, the database should return object as Object to db client, and let client re-cast the object and invoke the methods.
3. To access the Fields, you can do it with the 2 ways above.

Here is a simple example with java.lang.reflect.*
        Object obj=(Object) anObjectInputStream.readObject();
        Class class=obj.getClass();
        String class_name=class.getName(); // you can get the name of the class
        Method[] methods=class.getMethods(); // you can get definitions of all methods of the class
        Method method0=methods[0]; // get the first method
        Class[] paraClasses=method0.getParameterTypes(); // get the class type of the method.
        // ..........
Of cause, if you get enough information , you can invoke the methods dynamically!
But it's not easy and not efficient for programming.
Take a look at the package java.lang.reflect.*   you will get all information that you need.
0
 
thresholdCommented:
Here is one concept of Java Program:

Who wants to use/invoke the Object = Who knows the information of the Object = Who re-cast the Object.

so... You re-cast it when you use it!

Hope it will clarify something more.
0
 
maddy051398Author Commented:
So what I wanted to do wasn't possible, but now there's a lot of information here that may be useful.

Thanks,
Maddy.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 7
  • 2
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now