How to Instantiate a Class by Name in Java

Is there a way to instantiate a class by name in Java?

Two ways:

Method 1 - only for classes having a no-arg constructor

If your class has a no-arg constructor, you can get a Class object using Class.forName() and use the newInstance() method to create an instance (though beware that this method is often considered evil because it can defeat Java's checked exceptions).

For example:

Class<?> clazz = Class.forName("java.util.Date");
Object date = clazz.newInstance();

Method 2

An alternative safer approach which also works if the class doesn't have any no-arg constructors is to query your class object to get its Constructor object and call a newInstance() method on this object:

Class<?> clazz = Class.forName("com.foo.MyClass");
Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class);
Object instance = constructor.newInstance("stringparam", 42);

Both methods are known as reflection. You will typically have to catch the various exceptions which can occur, including things like:

  • the JVM can't find or can't load your class
  • the class you're trying to instantiate doesn't have the right sort of constructors
  • the constructor itself threw an exception
  • the constructor you're trying to invoke isn't public
  • a security manager has been installed and is preventing reflection from occurring

Instantiate object from class name as string

You can create an instance of a class and run its methods without ever having to import the class in your code using reflection:

Class clazz = Class.forName("com.whatever.MyClass");
Object instance = clazz.newInstance(); // or use the given instance
clazz.getMethod("myMethod").invoke(instance);

Java how to instantiate a class from string

"Using java.lang.reflect" will answer all your questions. First fetch the Class object using Class.forName(), and then:

If I want to instantiate a class that I retrieved with forName(), I have to first ask it for a java.lang.reflect.Constructor object representing the constructor I want, and then ask that Constructor to make a new object. The method getConstructor(Class[] parameterTypes) in Class will retrieve a Constructor; I can then use that Constructor by calling its method newInstance(Object[] parameters):

Class myClass = Class.forName("MyClass");

Class[] types = {Double.TYPE, this.getClass()};
Constructor constructor = myClass.getConstructor(types);

Object[] parameters = {new Double(0), this};
Object instanceOfMyClass = constructor.newInstance(parameters);

There is a newInstance() method on Class that might seem to do what you want. Do not use it. It silently converts checked exceptions to unchecked exceptions.

Note that this method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler. The Constructor.newInstance method avoids this problem by wrapping any exception thrown by the constructor in a (checked) InvocationTargetException.

Using a string to instantiate a class

I'm not sure I understand correctly, seems weird no one else mentioned this yet:

Map<Character, ShapeFactory> dict = new HashMap<>();
dict.put('C', new CircleFactory());
dict.put('R', new RectangleFactory());
dict.put('T', new TriangleFactory());

...

ShapeFactory factory = dict.get(symbol);
Shape shape = factory.create(data);

Can I Instantiate a class using the class object? What about Constructors?

You cannot construct new classes this way.

If you have the name of a class you can use Class.forName(className) to load/reference a class.

If you have the byte code for a class you want to create you can have a class loader load the byte code and give you the class. This is likely to be more advanced than you intended.

Creating an instance using the class name and calling constructor

Yes, something like:

Class<?> clazz = Class.forName(className);
Constructor<?> ctor = clazz.getConstructor(String.class);
Object object = ctor.newInstance(new Object[] { ctorArgument });

That will only work for a single string parameter of course, but you can modify it pretty easily.

Note that the class name has to be a fully-qualified one, i.e. including the namespace. For nested classes, you need to use a dollar (as that's what the compiler uses). For example:

package foo;

public class Outer
{
public static class Nested {}
}

To obtain the Class object for that, you'd need Class.forName("foo.Outer$Nested").



Related Topics



Leave a reply



Submit