Backend Development 8 min read

Five Ways to Create Objects in Java and Their Bytecode

This article explains five Java object‑creation techniques—using the new keyword, Class.newInstance, Constructor.newInstance, clone, and deserialization—shows their bytecode differences, provides a complete Employee example, and demonstrates each method with runnable code and output.

Java Captain
Java Captain
Java Captain
Five Ways to Create Objects in Java and Their Bytecode

As Java developers we often create many objects, typically using dependency‑injection frameworks like Spring, but there are several ways to instantiate objects directly. This article covers the five common techniques and shows the corresponding bytecode.

1. Using the new keyword

The simplest and most common method, which invokes any constructor (no‑arg or with parameters).

Employee emp1 = new Employee();
0: new #19 // class org/programming/mitra/exercises/Employee
3: dup
4: invokespecial #21 // Method org/programming/mitra/exercises/Employee."":()V

2. Using Class.newInstance()

This reflection‑based approach calls the no‑arg constructor.

Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance();
Employee emp2 = Employee.class.newInstance();
51: invokevirtual #70 // Method java/lang/Class.newInstance:()Ljava/lang/Object;

3. Using Constructor.newInstance()

Also reflection‑based, but allows invoking constructors with arguments or private constructors.

Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp3 = constructor.newInstance();
111: invokevirtual #80 // Method java/lang/reflect/Constructor.newInstance:([Ljava/lang/Object;)Ljava/lang/Object;

Both reflection methods ultimately rely on Class.newInstance , which is why many frameworks prefer the Constructor variant.

4. Using clone()

Cloning creates a new object by copying the original's fields without invoking any constructor. The class must implement Cloneable and override clone() .

Employee emp4 = (Employee) emp3.clone();
162: invokevirtual #87 // Method org/programming/mitra/exercises/Employee.clone ()Ljava/lang/Object;

5. Using Deserialization

When an object is deserialized, the JVM creates a new instance without calling a constructor. The class must implement Serializable .

ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp5 = (Employee) in.readObject();
261: invokevirtual #118 // Method java/io/ObjectInputStream.readObject:()Ljava/lang/Object;

Bytecode analysis shows that only the new method uses invokespecial to call a constructor; the other four methods result in invokevirtual calls.

Example Employee Class

class Employee implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    public Employee() { System.out.println("Employee Constructor Called..."); }
    // getters, setters, hashCode, equals, toString omitted for brevity
    @Override
    public Object clone() {
        try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; }
    }
}

Demo Program

public class ObjectCreation {
    public static void main(String[] args) throws Exception {
        Employee emp1 = new Employee(); emp1.setName("Naresh"); System.out.println(emp1 + ", hashcode : " + emp1.hashCode());
        Employee emp2 = (Employee) Class.forName("org.programming.mitra.exercises.Employee").newInstance(); emp2.setName("Rishi"); System.out.println(emp2 + ", hashcode : " + emp2.hashCode());
        Constructor<Employee> constructor = Employee.class.getConstructor();
        Employee emp3 = constructor.newInstance(); emp3.setName("Yogesh"); System.out.println(emp3 + ", hashcode : " + emp3.hashCode());
        Employee emp4 = (Employee) emp3.clone(); emp4.setName("Atul"); System.out.println(emp4 + ", hashcode : " + emp4.hashCode());
        // Serialization
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("data.obj")); out.writeObject(emp4); out.close();
        // Deserialization
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
        Employee emp5 = (Employee) in.readObject(); in.close(); emp5.setName("Akash"); System.out.println(emp5 + ", hashcode : " + emp5.hashCode());
    }
}

Running the program produces output showing constructor calls for the first three methods and only hashcode differences for the clone and deserialization approaches.

Employee Constructor Called...
Employee [name=Naresh], hashcode : -1968815046
Employee Constructor Called...
Employee [name=Rishi], hashcode : 78970652
Employee Constructor Called...
Employee [name=Yogesh], hashcode : -1641292792
Employee [name=Atul], hashcode : 2051657
Employee [name=Akash], hashcode : 63313419
JavaReflectionObject Creationdeserializationclone
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.