Java
Programming
Constructor Arguments
Class.newInstance()
Object-Oriented Programming

Can I use Class.newInstance() with constructor arguments?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

No, Class.newInstance() cannot call a constructor with arguments. It only tries to invoke an accessible zero-argument constructor, and in modern Java it is also deprecated in favor of better reflection APIs.

What Class.newInstance() Actually Does

This method is equivalent to "give me an instance of this class using the no-arg constructor if one exists and is accessible." It does not let you choose a constructor signature, and it does a poor job of surfacing checked exceptions thrown by the constructor.

That is why current Java code should prefer getDeclaredConstructor(...).newInstance(...).

The Correct Reflection API

If you need a constructor that takes arguments, first resolve the constructor by parameter types, then invoke it:

java
1import java.lang.reflect.Constructor;
2
3public class Person {
4    private final String name;
5    private final int age;
6
7    public Person(String name, int age) {
8        this.name = name;
9        this.age = age;
10    }
11
12    @Override
13    public String toString() {
14        return name + " (" + age + ")";
15    }
16
17    public static void main(String[] args) throws Exception {
18        Constructor<Person> ctor =
19            Person.class.getDeclaredConstructor(String.class, int.class);
20
21        Person p = ctor.newInstance("Ava", 30);
22        System.out.println(p);
23    }
24}

This is the standard pattern because it makes the constructor choice explicit and works with argument lists of any supported shape.

Working with Non-Public Constructors

If the constructor is not public, you can still access it with declared reflection and accessibility overrides, subject to the normal Java access rules and module boundaries:

java
1Constructor<Person> ctor =
2    Person.class.getDeclaredConstructor(String.class, int.class);
3
4ctor.setAccessible(true);
5Person p = ctor.newInstance("Ava", 30);

Be careful with this in modern Java. Strong encapsulation and module boundaries can make deep reflective access fail in environments that do not open the package.

Why Class.newInstance() Is a Bad Fit

Even if your class has a zero-argument constructor, Class.newInstance() is still usually the wrong tool:

  • it cannot select parameterized constructors
  • it propagates errors less clearly
  • it has been deprecated for years

The replacement is not complicated:

java
MyType value = MyType.class.getDeclaredConstructor().newInstance();

That form works for no-arg construction and keeps your code aligned with the modern reflection API.

When Reflection Is the Wrong Approach

Many uses of reflective instantiation are better replaced with a factory, dependency injection, or a map of known constructors. Reflection is powerful, but it weakens compile-time safety and becomes harder to maintain once constructors change.

For example, instead of dynamically guessing argument types at runtime, a simple supplier registry may be clearer:

java
Map<String, Supplier<Object>> registry = Map.of(
    "defaultPerson", Person::new
);

That only works for zero-arg creation, but the design lesson is broader: use reflection when you truly need runtime type discovery, not as the default construction mechanism.

Exception Handling

Reflective constructor calls can throw several checked exceptions, including:

  • 'NoSuchMethodException'
  • 'InstantiationException'
  • 'IllegalAccessException'
  • 'InvocationTargetException'

The last one is especially important because it wraps exceptions thrown by the constructor itself. Good error handling should inspect the underlying cause rather than treating reflection failure as a single generic error.

Common Pitfalls

The biggest mistake is assuming Class.newInstance() supports arguments because newInstance sounds generic. It does not.

Another issue is matching the wrong parameter types. Reflection requires exact constructor signatures, so Integer.class is not the same thing as int.class.

Developers also forget constructor visibility and module access rules, especially when moving older reflection code to newer JDKs.

Finally, do not ignore the deprecation. Even when the no-arg case works today, the replacement API is clearer and safer.

Summary

  • 'Class.newInstance() only supports accessible zero-argument constructors.'
  • It cannot instantiate with constructor arguments.
  • Use getDeclaredConstructor(...).newInstance(...) instead.
  • Be careful with visibility, primitive-versus-wrapper types, and wrapped constructor exceptions.
  • Prefer factories or dependency injection when reflection is not truly necessary.

Course illustration
Course illustration

All Rights Reserved.