如何在运行时创建指定类类型的对象?

时间:2012-06-07 20:03:58

标签: java

假设我有这样的方法

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

如何在Java中执行此操作?

6 个答案:

答案 0 :(得分:4)

虽然每个人都很快指出Class.forName("com.myorg.MyClass");和相关的newInstance()方法,但重要的是要记住它只会调用不带参数的默认构造函数。

如果您发现需要调用类的特定构造函数,则需要使用反射来查找正确的构造函数,然后调用它。

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

列出了所有构造函数and a tutorial is available here

找到所需的构造函数后,可以这样调用

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

又是from the tutorial about reflection

答案 1 :(得分:2)

请注意,在您的示例中,您将className作为Class对象传递,因此您可以这样做:

className.newInstance();

但我怀疑你正在寻找一种方法将类名作为String传递,在这种情况下,程序是(这里classNameString):< / p>

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

请注意,您还需要处理两个调用引发的Exceptions

这是最简单的情况,并不涵盖,例如具体的构造者。

请参阅the docs了解课程。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

如果我正确理解了这个问题。应该像这样创建给定类的对象:

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

    }
}

答案 4 :(得分:0)

您可以使用Class.newInstance()(仅用于零参数构造函数)或Constructor.newInstance()来执行您想要的操作。有关工作示例,请参阅here

答案 5 :(得分:0)

取决于你是否已经获得一个Object或者只是一个带有classname的String,我将执行以下操作:

  1. 使用反射,使用您的类名字符串实例化上述对象,如上所述;如果您已经获得了一个对象,则可以跳过此步骤
  2. 确保您的对象继承自通过instanceof提供公共方法readAndAnalyze(...)的类或接口
  3. 通过instanceof
  4. 将您的对象投射到上面检查过的一个类
  5. 调用方法并继续