Solved

Calling all OO gurus

Posted on 1998-07-22
15
180 Views
Last Modified: 2012-05-04
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
Comment
Question by:maddy051398
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 2
  • 2
  • +3
15 Comments
 
LVL 1

Expert Comment

by:dryang
ID: 1227498


   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
 

Author Comment

by:maddy051398
ID: 1227499
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
 
LVL 16

Expert Comment

by:imladris
ID: 1227500
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:maddy051398
ID: 1227501
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
 
LVL 1

Expert Comment

by:dryang
ID: 1227502
hi maddy,
I see the light now. Good luck to your programming  :)
0
 

Author Comment

by:maddy051398
ID: 1227503
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
 

Expert Comment

by:ronaldyang
ID: 1227504
Here's an answer!  Accept me please!
0
 

Author Comment

by:maddy051398
ID: 1227505
But I need the 100 points for something useful, probably!
0
 
LVL 2

Expert Comment

by:shchuka
ID: 1227506
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
 

Author Comment

by:maddy051398
ID: 1227507
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
 
LVL 2

Expert Comment

by:shchuka
ID: 1227508
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
 

Author Comment

by:maddy051398
ID: 1227509
Casting to the base Interface class means ObjectInputStream.readObject() doesn't get the correct (derived) object data from the stream.

Maddy
0
 
LVL 2

Accepted Solution

by:
threshold earned 100 total points
ID: 1227510
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
 
LVL 2

Expert Comment

by:threshold
ID: 1227511
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
 

Author Comment

by:maddy051398
ID: 1227512
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

Featured Post

The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
In this post we will learn different types of Android Layout and some basics of an Android App.
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question