Dynamically converting java object of Object class to a given class when class name is known
Asked Answered
B

7

47

Yeah, I know. Long title of question... So I have class name in string. I'm dynamically creating object of that class in this way:

String className = "com.package.MyClass";   
Class c = Class.forName(className);
Object obj = c.newInstance();

How I can dynamically convert that obj to MyClass object? I can't write this way:

MyClass mobj = (MyClass)obj;

...because className can be different.

Boraginaceous answered 12/12, 2009 at 13:2 Comment(1)
That code doesn't convert: it typecasts. Is that what you mean?Tonnage
T
28

you don't, declare an interface that declares the methods you would like to call:

public interface MyInterface
{
  void doStuff();
}

public class MyClass implements MyInterface
{
  public void doStuff()
  {
    System.Console.Writeln("done!");
  }
}

then you use

MyInterface mobj = (myInterface)obj;
mobj.doStuff();

If MyClassis not under your control then you can't make it implement some interface, and the other option is to rely on reflection (see this tutorial).

Tulle answered 12/12, 2009 at 13:4 Comment(4)
Although I do agree with Greg in most cases; I found myself in a situation where I don't want to have to know about interfaces. I don't know if that tutorial above addressed this issue, but none of those I'd found in my research on the issue did. Here's a dynamic solution I came up with (you would need to know the name of the method/field as well as the name of the class): forums.sun.com/thread.jspa?threadID=5419973Finch
Although the question is quite old, but in my opinion there is a much better way to implement the given functionality (Invoking the functions). URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { parentDirectory.toURI().toURL() }); Class<?> myClass = classLoader.loadClass(className ); Method doStuff= myClass.getDeclaredMethod("doStuff"); doStuff.invoke(helloClass.newInstance()); Aquifer
this can some how server the purpose, I use it in many cases where I could be having classes with commons functionalities.Spoony
This solution does not work, if we want to put the resulting object into container (or use with other Generics) unlike the solution suggested below with myClassObject.cast(otherObject).Shamekashameless
E
99

I think its pretty straight forward with reflection

MyClass mobj = MyClass.class.cast(obj);

and if class name is different

Object newObj = Class.forName(classname).cast(obj);
Evyn answered 22/4, 2013 at 20:2 Comment(4)
This is simple and straightforward. Thanks Lukas.Hakeem
This is the best solution ever , I've been searching for such like this approach and finally found itZoogeography
I am using this but it's not working with primitives. boolean.class.cast(new Boolean(false)); is throwing ClassCastException. Any idea how I can remedy this?Weightless
@jDub9 you are trying to cast a Boolean (Non-primitive) to a boolean (primitive)Pitman
T
28

you don't, declare an interface that declares the methods you would like to call:

public interface MyInterface
{
  void doStuff();
}

public class MyClass implements MyInterface
{
  public void doStuff()
  {
    System.Console.Writeln("done!");
  }
}

then you use

MyInterface mobj = (myInterface)obj;
mobj.doStuff();

If MyClassis not under your control then you can't make it implement some interface, and the other option is to rely on reflection (see this tutorial).

Tulle answered 12/12, 2009 at 13:4 Comment(4)
Although I do agree with Greg in most cases; I found myself in a situation where I don't want to have to know about interfaces. I don't know if that tutorial above addressed this issue, but none of those I'd found in my research on the issue did. Here's a dynamic solution I came up with (you would need to know the name of the method/field as well as the name of the class): forums.sun.com/thread.jspa?threadID=5419973Finch
Although the question is quite old, but in my opinion there is a much better way to implement the given functionality (Invoking the functions). URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { parentDirectory.toURI().toURL() }); Class<?> myClass = classLoader.loadClass(className ); Method doStuff= myClass.getDeclaredMethod("doStuff"); doStuff.invoke(helloClass.newInstance()); Aquifer
this can some how server the purpose, I use it in many cases where I could be having classes with commons functionalities.Spoony
This solution does not work, if we want to put the resulting object into container (or use with other Generics) unlike the solution suggested below with myClassObject.cast(otherObject).Shamekashameless
W
4
@SuppressWarnings("unchecked")
private static <T extends Object> T cast(Object obj) {
    return (T) obj;
}
Worl answered 7/3, 2019 at 20:42 Comment(0)
M
3

You don't have to convert the object to a MyClass object because it already is. What you really want to do is to cast it, but since the class name is not known at compile time, you can't do that, since you can't declare a variable of that class. My guess is that you want/need something like "duck typing", i.e. you don't know the class name but you know the method name at compile time. Interfaces, as proposed by Gregory, are your best bet to do that.

Mcmillen answered 12/12, 2009 at 13:14 Comment(1)
If you really need this sort of feature, consider another language - groovy is one that runs on the jvm but has the feature you want.Evesham
E
2

If you didnt know that mojb is of type MyClass, then how can you create that variable?

If MyClass is an interface type, or a super type, then there is no need to do a cast.

Evesham answered 12/12, 2009 at 13:8 Comment(0)
T
0

If you want to cast an object (ob1) to a class (classA), you can use the following code.

classA instance = (classA) ob1;

Toothpick answered 10/11, 2021 at 10:28 Comment(0)
T
0

One can also use ObjectMapper class to convert an object to a specific type.

e.g.


public ClassA convert(Object request) 
{
    ObjectMapper mapper = new ObjectMapper();
    ClassA classAObj = mapper.convertValue(request, ClassA.class);

    return classAObj;
}

Talkie answered 3/3 at 6:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.