CodeBlue
CodeBlue

Reputation: 15389

How to create an object of a specified class type at runtime?

Suppose I have a method like this

 public void readAndInitialize(StringReader reader, Class className)
  {
    // Here, I want to to something like this - 

   // obj = new (object of the specified className)

      obj.readAndInitialize(reader);
  }

How to do this in Java?

Upvotes: 1

Views: 1335

Answers (6)

bully
bully

Reputation: 5994

depending on if you get an Object already or just a String with the classname, i would do the following:

  1. instantiate the object like described above, using reflection, with the string of your classname; if you get an object already, you can skip this step
  2. Ensure your object inherits from a class or interface which serves a public method readAndAnalyze(...) via instanceof
  3. cast your object to the class you checked one step above via instanceof
  4. call the method and go on

Upvotes: 0

pb2q
pb2q

Reputation: 59607

Note that in your example you're passing className as a Class object, and so you could do:

className.newInstance();

But I suspect that you're looking for a way to pass the class name as a String, in which case the procedure is (here className is a String):

Class class = Class.forName(className());
Object obj = class.newInstance();

Note that you'll also need to handle the Exceptions thrown by both calls.

This is the simplest case, and doesn't cover, e.g. specific constructors.

See the docs for Class.

Upvotes: 2

Edwin Buck
Edwin Buck

Reputation: 70909

While everyone is quick to point out Class.forName("com.myorg.MyClass"); and the related newInstance() method, it is important to remember that it will only call a default constructor taking no parameters.

If you find that you need to call a particular constructor of the class, you need to use reflections to find the correct constructor, and then call it.

import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import static java.lang.System.out;

public class ConstructorSift {
    public static void main(String... args) {
    try {
        Class<?> cArg = Class.forName(args[1]);

        Class<?> c = Class.forName(args[0]);
        Constructor[] allConstructors = c.getDeclaredConstructors();
        for (Constructor ctor : allConstructors) {
        Class<?>[] pType  = ctor.getParameterTypes();
        for (int i = 0; i < pType.length; i++) {
            if (pType[i].equals(cArg)) {
            out.format("%s%n", ctor.toGenericString());

            Type[] gpType = ctor.getGenericParameterTypes();
            for (int j = 0; j < gpType.length; j++) {
                char ch = (pType[j].equals(cArg) ? '*' : ' ');
                out.format("%7c%s[%d]: %s%n", ch,
                       "GenericParameterType", j, gpType[j]);
            }
            break;
            }
        }
        }

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}

lists all constructors, and a tutorial is available here.

Once you have found the desired constructor, you can call it like so

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static java.lang.System.out;

class EmailAliases {
    private Set<String> aliases;
    private EmailAliases(HashMap<String, String> h) {
    aliases = h.keySet();
    }

    public void printKeys() {
    out.format("Mail keys:%n");
    for (String k : aliases)
        out.format("  %s%n", k);
    }
}

public class RestoreAliases {

    private static Map<String, String> defaultAliases = new HashMap<String, String>();
    static {
    defaultAliases.put("Duke", "duke@i-love-java");
    defaultAliases.put("Fang", "fang@evil-jealous-twin");
    }

    public static void main(String... args) {
    try {
        Constructor ctor = EmailAliases.class.getDeclaredConstructor(HashMap.class);
        ctor.setAccessible(true);
        EmailAliases email = (EmailAliases)ctor.newInstance(defaultAliases);
        email.printKeys();

        // production code should handle these exceptions more gracefully
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    }
    }
}

which is again, from the tutorial about reflection.

Upvotes: 4

loscuropresagio
loscuropresagio

Reputation: 1952

You can do what you want by using Class.newInstance() (only for zero-argument constructor) or Constructor.newInstance(). See here for a working example.

Upvotes: 0

Paulius Matulionis
Paulius Matulionis

Reputation: 23415

If I correctly understand the question. An object from given class should be created like this:

if (yourClass != null) {
    Object yourObject = null;
    try {
        yourObject = yourClass.newInstance();
    } catch (InstantiationException e) {
        LOGGER.error("", e);            
    } catch (IllegalAccessException e) {
        LOGGER.error("", e);

    }
}

Upvotes: 1

JuanZe
JuanZe

Reputation: 8157

public void readAndInitialize(StringReader reader, String className)  //className changed to String
  {
    // Here, I want to to something like this - 
   // obj = new (object of the specified className)

      //try this:
      Class myclass = Class.forName(className);
      Object obj = myclass.newInstance();

      obj.readAndInitialize(reader);
  }

Upvotes: 1

Related Questions