Insights into Company Bills & Payments
← Java

Constructors

Understand the idea. Compare it. Explain it. Test yourself.

Question 11 of 12

Can constructors be inherited?

Solution and explanation

Answer

No. Constructors are not inherited and cannot be overridden. A subclass must declare its own constructors, and each one calls a parent constructor with super(...).

class Vehicle {
    Vehicle(String regNo) { }
}

class Bike extends Vehicle {
    // No constructor declared: the compiler adds Bike() { super(); }
    // But Vehicle has no no-arg constructor → compile error.
}

class Car extends Vehicle {
    Car(String regNo) { super(regNo); }    // correct: declare and chain
}

new Car("DL3C1234");          // fine
// new Car();                 // error: Car has no no-arg constructor even though Vehicle might

Why not inherited?

  • A constructor's name is its class name; a parent constructor named Vehicle makes no sense for creating a Car.
  • A subclass usually has extra fields that the parent constructor knows nothing about, so inheriting it would create partially initialised objects.

Related facts

  • Constructors cannot be overridden, so there is no runtime polymorphism for constructors.
  • They can be overloaded within a class.
  • Records and Lombok (@AllArgsConstructor, @RequiredArgsConstructor) generate constructors to reduce boilerplate.
Practice explaining this
Question 12 of 12

How are private constructors used in the Singleton pattern?

Solution and explanation

Idea

Singleton ensures a class has exactly one instance and gives a global access point to it. The private constructor stops other code from calling new; a static method or field hands out the single instance.

1. Eager initialisation

public class ConfigManager {
    private static final ConfigManager INSTANCE = new ConfigManager();   // created when the class loads
    private ConfigManager() { }
    public static ConfigManager getInstance() { return INSTANCE; }
}

Simple and thread-safe (class loading is thread-safe), but the object is created even if never used.

2. Lazy with double-checked locking

public class DbConnectionPool {
    private static volatile DbConnectionPool instance;    // volatile prevents seeing a half-built object
    private DbConnectionPool() { }

    public static DbConnectionPool getInstance() {
        if (instance == null) {                            // 1st check without locking (fast path)
            synchronized (DbConnectionPool.class) {
                if (instance == null) {                    // 2nd check inside the lock
                    instance = new DbConnectionPool();
                }
            }
        }
        return instance;
    }
}

3. Bill Pugh holder (lazy and thread-safe without locks)

public class Logger {
    private Logger() { }
    private static class Holder { static final Logger INSTANCE = new Logger(); }
    public static Logger getInstance() { return Holder.INSTANCE; }   // Holder loads on first call
}

4. Enum singleton (recommended by Effective Java)

public enum IdGenerator {
    INSTANCE;
    private final AtomicLong next = new AtomicLong();
    public long nextId() { return next.incrementAndGet(); }
}
IdGenerator.INSTANCE.nextId();

Safe against reflection and serialization attacks automatically.

Breaking a singleton and the defences

AttackDefence
Reflection setAccessible(true)Throw from the constructor if an instance exists, or use an enum
Serialization creates a new objectImplement readResolve() returning INSTANCE, or use an enum
CloningDo not implement Cloneable, or throw in clone()

Note: in Spring, beans are singletons per container by default, so you rarely hand-write this pattern in Spring applications.

Practice explaining this

Showing questions 11–12 of 12