Create an Object Without the new Keyword in Java (7 Ways)

Learn 7 ways to create an object without the new keyword in Java, which ones skip the constructor, and what is deprecated or internal on Java 25.

Seven ways to create a Java object without new, grouped by whether the constructor runs

To create an object without the new keyword in Java, we call a constructor through reflection or a method handle, copy an existing object with clone() or deserialization, or call a factory method that runs new for us. Only clone(), deserialization and the internal Unsafe.allocateInstance() create an object without running its constructor.

Application code uses new almost everywhere. The other ways matter in frameworks and libraries, which create objects of classes they only know by name, copy objects, or rebuild them from bytes, and in interviews, where the question tests how well we know object creation.

The following example creates four Book objects without writing new Book(…). The Book class is defined in section 1.

Book byReflection = Book.class.getDeclaredConstructor(String.class).newInstance("Dune");   // Dune
Book byClone = byReflection.clone();                                                       // Dune
Book byFactory = Book.of("Emma");                                                          // Emma
Supplier<Book> maker = Book::new;
Book bySupplier = maker.get();                                                             // untitled

Notice that reflection, the factory method and the Supplier still run a Book constructor, whereas clone() copies the fields without one. We go through seven ways in total, check which ones work on Java 25 and which APIs are deprecated, and compare them in one table.

1. What new Does and What the Alternatives Skip

The expression new Book(“Dune”) does three things. The JVM allocates memory for the object, sets every field to its default value, such as null or 0, and runs the constructor, which assigns the real values. The alternatives differ in which of these steps they keep.

Seven ways to create a Java object without new, grouped by whether the constructor runs
Reflection, method handles and factories still run a constructor; clone(), deserialization and Unsafe skip it

Every example uses one small class. It counts its constructor calls in a static field, so we can see which ways run a constructor, and it implements Cloneable and Serializable for the copy-based ways.

class Book implements Cloneable, Serializable {
    static int constructorCalls = 0;
    String title;

    public Book() {
        this("untitled");
    }

    public Book(String title) {
        this.title = title;
        constructorCalls++;
    }

    static Book of(String title) {
        return new Book(title);
    }

    @Override
    public Book clone() {
        try {
            return (Book) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(e);      // cannot happen, Book is Cloneable
        }
    }

    @Override
    public String toString() {
        return title;
    }
}

2. Reflection with Constructor.newInstance()

Reflection finds a constructor at runtime and calls it with Constructor.newInstance(). We use it when the class is known only at runtime, for example from a configuration file, and it is how most dependency injection containers create beans.

Book reflected = Book.class.getDeclaredConstructor().newInstance();       // untitled
Object list = Class.forName("java.util.ArrayList").getDeclaredConstructor().newInstance();   // []

The older Class.newInstance() method has been deprecated since Java 9, and the replacement is getDeclaredConstructor().newInstance(). The old method rethrows any exception from the constructor, including checked exceptions that the compiler never sees, whereas the replacement wraps them in an InvocationTargetException. The Class.forName() and ClassLoader.loadClass() methods only load a class, so they always need one of these calls to create the object.

Reflection respects access rules. A private constructor needs setAccessible(true), and that call fails for classes in modules that do not open their packages to our code, such as java.base.

Constructor<String> hidden = String.class.getDeclaredConstructor(byte[].class, byte.class);
hidden.setAccessible(true);                    // InaccessibleObjectException: java.base does not open java.lang

Reflection also refuses some classes outright. An abstract class or an interface has nothing to instantiate, and enum constants cannot be created reflectively, which is why an enum is the safest singleton.

3. Method Handles with findConstructor()

A method handle is a typed reference to a method or constructor that we can call like a function, added in Java 7 in the java.lang.invoke package. MethodHandles.Lookup.findConstructor() returns a handle to a constructor. A handle stored in a static final field is a constant for the JIT compiler, so it can inline calls through the handle.

static Book newBookViaHandle(String title) {
    try {
        MethodHandle ctor = MethodHandles.lookup()
                .findConstructor(Book.class, MethodType.methodType(void.class, String.class));
        return (Book) ctor.invoke(title);
    } catch (Throwable t) {
        throw new IllegalStateException("cannot create Book", t);
    }
}
Book viaHandle = newBookViaHandle("Ivanhoe");                            // Ivanhoe

The method type always has void as its return type, because constructors return nothing, and the parameter types pick the constructor. The invoke() method declares Throwable, so a helper method like newBookViaHandle() keeps that catch block out of the calling code.

4. Copying an Object with clone()

The Object.clone() method allocates a new object of the same class and copies every field value, without calling a constructor. The class must implement Cloneable, otherwise clone() throws CloneNotSupportedException, and it must override clone() as public, because the version in Object is protected.

int callsBeforeClone = Book.constructorCalls;
Book original = Book.of("Persuasion");
Book cloned = original.clone();
boolean differentObject = cloned != original;                           // true
int cloneCalls = Book.constructorCalls - callsBeforeClone;              // 1, only Book.of() ran a constructor

The copy is shallow, so a field that refers to a list or another object refers to the same instance in both copies. For classes we design ourselves, a copy constructor or a static copyOf() method is clearer, as our guide to object cloning explains.

5. Deserialization with ObjectInputStream

Deserialization rebuilds an object from bytes that serialization wrote earlier. The ObjectInputStream class creates the object and sets the fields from the stream, without running the constructor of the Serializable class. It runs only the no-argument constructor of the first superclass that is not Serializable, which is Object for our Book.

static <T extends Serializable> T roundTrip(T object) throws IOException, ClassNotFoundException {
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    try (ObjectOutputStream out = new ObjectOutputStream(bytes)) {
        out.writeObject(object);
    }
    try (ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes.toByteArray()))) {
        @SuppressWarnings("unchecked")
        T copy = (T) in.readObject();
        return copy;
    }
}
Book saved = Book.of("Middlemarch");
int callsBeforeRead = Book.constructorCalls;
Book restored = roundTrip(saved);                                       // Middlemarch
int readCalls = Book.constructorCalls - callsBeforeRead;                // 0, no constructor ran

Records are the exception. Java deserializes a record through its canonical constructor, so the validation in that constructor runs on every read. Deserializing bytes from an untrusted source is dangerous, because a crafted stream can create objects that the constructors would have rejected. If the app must read such data, it sets an ObjectInputFilter that allows only the expected classes.

6. Factory Methods, Suppliers and Builders

A static factory method, a method reference such as Book::new, and a builder create objects without a new expression at the call site. They still run a constructor inside, or they return a cached object, which is something new can never do.

List<String> genres = List.of("drama", "poetry");                      // [drama, poetry]
LocalDate release = LocalDate.of(2026, 3, 14);                           // 2026-03-14
boolean cached = Integer.valueOf(127) == Integer.valueOf(127);          // true, same cached object
Optional<Book> maybe = Optional.of(Book.of("Emma"));                    // Optional[Emma]

Factory methods are the right choice in application code. The class keeps control over creation, can return a subtype or a cached instance, and gives the creation a name, such as LocalDate.of() or List.copyOf(). The factory pattern takes the idea further with a separate factory class.

7. Unsafe.allocateInstance() Without Any Constructor

The internal class sun.misc.Unsafe in the jdk.unsupported module can allocate an object and skip every constructor, so all fields keep their default values. Libraries that must skip constructors rely on it or on the similar internal ReflectionFactory class, for example Objenesis, which Mockito uses to create mocks of classes whose constructors need arguments.

Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
int callsBeforeUnsafe = Book.constructorCalls;
Book raw = (Book) unsafe.allocateInstance(Book.class);                  // null, title never set
int unsafeCalls = Book.constructorCalls - callsBeforeUnsafe;            // 0

On Java 25, allocateInstance() still works and is not deprecated. The memory-access methods of Unsafe were deprecated for removal by JEP 471 in Java 23, and since JEP 498 in Java 24 the JVM prints a warning on their first use, but allocateInstance() is not one of them. The compiler still warns that Unsafe is an internal API that may be removed, so application code never uses it.

8. Ways to Create an Object Without the new Keyword Compared

The two questions that decide the choice are whether the constructor runs and whether the API is safe to use in application code. The table answers both for Java 25, plus the objects that the language creates for us, such as string literals and autoboxed numbers.

WayRuns a constructorJava 25 statusTypical use
newYesStandardApplication code
Constructor.newInstance()YesStandardFrameworks, plugins, class names from configuration
Class.newInstance()YesDeprecated since Java 9Old code only, replace it
MethodHandles.Lookup.findConstructor()YesStandardLibraries that create many objects of a runtime class
clone()NoStandard, needs CloneableCopies of arrays and Cloneable classes
DeserializationNo (yes for records)Standard, filter untrusted inputCaches, session replication, legacy messaging
Factory method, Supplier, builderYes, insideStandardApplication code, readable creation
Unsafe.allocateInstance()NoInternal, not deprecatedMocking and serialization libraries
Literals, autoboxing, array initializersNot visibleStandardStrings, wrapper objects, arrays
String literal = "Dune";                                                 // "Dune", no new in our code
Integer boxed = 42;                                                      // 42, Integer.valueOf() runs for us
int[] pages = {120, 240};                                                // [120, 240]

9. Loading Plugins by Class Name

Say a reporting app lets each customer pick an export format in a configuration file, such as CSV or PDF. The app ships the exporters as classes that implement one interface, and it creates the configured exporter from its class name at startup.

interface Exporter {
    String export(List<String> rows);
}
class CsvExporter implements Exporter {
    public CsvExporter() {
    }

    public String export(List<String> rows) {
        return String.join(",", rows);
    }
}
String className = CsvExporter.class.getName();          // read from the configuration file in a real app
Exporter exporter = Class.forName(className).asSubclass(Exporter.class).getDeclaredConstructor().newInstance();
String csv = exporter.export(List.of("id", "title"));                    // "id,title"

The asSubclass() call fails with a ClassCastException when the configured class does not implement Exporter, so a wrong class name stops the app at startup instead of in the middle of an export. For plugins packaged as JAR files, java.util.ServiceLoader does the same lookup through a provider file and needs no class names in the configuration.

10. Object Creation FAQs

Interviewers and readers ask about constructors, singletons and abstract classes when this topic comes up.

10.1. Can we create an object without calling its constructor?

Yes. The clone() method, deserialization of a non-record class and Unsafe.allocateInstance() create an object without running its constructor. The other ways call a constructor, either through reflection or inside a factory method.

10.2. Is Class.newInstance() deprecated?

Yes, since Java 9, but it is not marked for removal. Replace clazz.newInstance() with clazz.getDeclaredConstructor().newInstance(), which reports constructor exceptions as InvocationTargetException.

10.3. Can reflection break a singleton?

Yes, for a singleton with a private constructor in our own module, because setAccessible(true) lets us call the constructor a second time. An enum singleton is safe, because reflection refuses to create enum constants.

enum Config { INSTANCE }

10.4. Can we create an object of an abstract class without new?

No. Reflection on an abstract class throws InstantiationException, and clone() or deserialization always produce an object of a concrete class. An anonymous subclass works, but it needs the new keyword.

11. Conclusion

Java creates objects without the new keyword through reflection, method handles, clone(), deserialization, factory methods and the internal Unsafe class. Reflection and method handles still call a constructor, and getDeclaredConstructor().newInstance() replaces the deprecated Class.newInstance().

Only clone(), deserialization and Unsafe.allocateInstance() skip the constructor, which is useful for copies and libraries but bypasses the checks in the constructor. In application code, a factory method or a builder gives the same flexibility without that risk.

12. References

Happy Learning !!

Source Code on Github

Leave a Comment

  1. How will you make object of parameterized constructor using the newInstance method of Class class.
    Scenerio:
    class MyClass{
    MyClass(String methodType){
    System.out.println(“I am calling this constructor using ” + methodType);
    }
    }

    public class ABC{
    public static void main(String[] args) {
    //In below scenerio where I will pass my constructor’s parameter value
    MyClass meth2 = (MyClass) Class. forName(“packagePath.MyClass“).newInstance();
    }
    }

  2. What about this scenario???

    String str1=new String(“Hello”);
    String str2=s1.concat(” World”);

    In this case we are not using any of the methods mentioned above right,but a new String object is getting created in String Constant Pool.

    • Hi Mohan,

      There will be certain scenarios
      1. Does not have default constructor and having parameterised constructor.
      — In this case you will be using any of the ways mentioned above.
      2. Does not have any constructor.
      — JVM does the work on our behalf, by creating a default one. For this case also you have to use any of the above mentioned except the deserialisation and using ReflectionAPI.

  3. How about when we make the class as static and directly use its instance. Does this also counts under object creation without new keyword. ?

  4. There are two reflective methods for creating instances of classes: java.lang.reflect.Constructor.newInstance() and Class.newInstance() https://docs.oracle.com/en/java/javase/22/.

    So isn’t the first, second and last choice just point to same thing, i.e. getting instance of Class and running newInstance() method on it (of course in different ways). there by point to same thing that is reflection?

  5. Using clone() of java.lang.Object part is wrong because the clone method is protected. You forget to write that we should implement our public instance of clone() in NewClass or super class of NewClass…

    • I disagree. Reason is that in few examples, I am using an existing object to create a new one e.g. clone(). Yes, that exiting object was created with new keyword.

  6. final Value v = Value.class.getConstructor(int.class, int.class, double.class).newInstance(_xval1,_xval2,_pval);

  7. Hi Lokesh:

    Can you specify under what circumstances it is better to use each approach ??

    What would be the disadvantage of using the new keyword in some situation ?

    • There are no advantages or disadvantages.. they are simply another ways to achieve this. I believe, I outcome is same, means matter a little less, if not at all.

      Also, you might know that most frameworks around us in java world use reflection or class loader or object creation, they seldom use new keyword.

    • with new keyword , you are tightly coupling your code , whereas with the other techniques , you can make object depending on the some condition just by by passing the class name.

Comments are closed.

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.