简体   繁体   中英

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?

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 .

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, eg specific constructors.

See the docs for Class.

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);
  }

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);

    }
}

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM