Back to Reflection & Object Creation
Q1Question 1 of 2

What are the different ways to create an object in Java?

Key Concepts
  • new keyword: the most common way – Account a = new Account("SAV2001")
  • Reflection: Class.forName("com.bank.Account").getDeclaredConstructor().newInstance()
  • clone(): creates a copy of an existing object (see Object Cloning topic)
  • Deserialization: ObjectInputStream.readObject() creates an object from bytes without calling the constructor
  • Factory method: Account.create("SAV2001") – encapsulates construction logic
  • Spring DI: the framework creates objects via reflection and injects dependencies

Definition

Objects can be created via new, reflection, clone, deserialization, or factory methods. new is the most common. Spring uses reflection internally for dependency injection.

Six ways to create objects:

  • new: Account a = new Account(...) – calls the constructor directly. Most common.
  • Reflection: Class.forName(...).getDeclaredConstructor().newInstance() – creates objects dynamically by name.
  • clone(): account.clone() – copies an existing object.
  • Deserialization: ObjectInputStream.readObject() – creates from bytes without constructor.
  • Factory method: Account.create(...) – static method that encapsulates construction.
  • DI framework: Spring creates beans via reflection based on annotations.

Six ways to open a bank account: walk into the branch (new), send a remote instruction with the account type name (reflection), photocopy an existing passbook (clone), restore from backup (deserialization), ask the relationship manager to handle it (factory), or let the branch manager assign one automatically (Spring DI).

Understanding the Concepts

1. new keyword

JAVA
Account rajesh = new Account("SAV2001", new BigDecimal("500000"));

Most common. Calls the constructor. Type checked at compile time.

2. Reflection

JAVA
Class<?> clazz = Class.forName("com.bank.core.Account");
Constructor<?> ctor = clazz.getDeclaredConstructor(String.class, BigDecimal.class);
Account a = (Account) ctor.newInstance("SAV2001", new BigDecimal("500000"));

Used by frameworks (Spring, JPA, Jackson) to create objects dynamically. Slower than new.

3. clone()

JAVA
Account copy = original.clone();  // shallow copy, requires Cloneable

4. Deserialization

JAVA
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("account.ser"));
Account a = (Account) ois.readObject();  // no constructor called!

Warning: deserialization bypasses the constructor entirely. Security risk with untrusted data.

5. Factory method

JAVA
public class Account {
    public static Account createSavings(String id, BigDecimal balance) {
        Account a = new Account(id, balance);
        a.type = AccountType.SAVINGS;
        return a;
    }
}

Account sa = Account.createSavings("SAV2001", new BigDecimal("500000"));

Factory methods can return cached instances, subclasses, or validated objects.

6. Spring DI

JAVA
@Component
public class AccountService {
    // Spring creates this bean via reflection and injects the repository
    private final AccountRepository repo;
    public AccountService(AccountRepository repo) { this.repo = repo; }
}

What should a senior engineer know?

  • Reflection is slow (~10x slower than new) but the JVM caches reflection metadata after first use.
  • Deserialization is a security risk. Never deserialize untrusted data. Prefer JSON/Protobuf.
  • Record classes can be created with new: new AccountSummary("SAV2001", balance) – the canonical constructor.
  • Enum constants cannot be created with new. They are created at class load time.

What are common mistakes?

A common mistake is not understanding the concept fully before using it in production banking applications.

Wrong approach:

JAVA
package com.bank.service;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, double amount) {
        // WRONG: using double for money
        double balance = getBalance(fromAccount);
        balance = balance - amount;
    }
    private double getBalance(String id) { return 10000.0; }
}

Correct approach:

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // CORRECT: using BigDecimal for money
        BigDecimal balance = getBalance(fromAccount);
        balance = balance.subtract(amount);
    }
    private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}

Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.

Visual Overview

DIAGRAM
  6 ways to create objects:

  1. new Account(...)           ← most common, compile-time checked
  2. Class.forName(...).newInstance() ← reflection, used by frameworks
  3. account.clone()            ← shallow copy
  4. ObjectInputStream.readObject() ← deserialization, bypasses constructor
  5. Account.create(...)        ← factory method, encapsulates logic
  6. Spring @Component          ← framework creates via reflection + DI

Key Takeaway

Java has six ways to create objects: new, reflection, clone, deserialization, factory methods, and framework DI. New is the most common and fastest. Reflection is used by frameworks like Spring and JPA. Factory methods encapsulate creation logic. And deserialization bypasses the constructor entirely, which is a security concern.

One sentence to remember: new is the standard, reflection is for frameworks, factory is for encapsulation, and deserialization bypasses the constructor.

---

Share
Use ← → arrow keys to navigate