Creating a Person object shouldn't require separate calls to set name and age. Constructors let you initialize an object in one step: new Person("Alice", 30) creates a fully-formed object immediately.

Default constructor

The constructor Java provides when you don't write one.

DefaultConstructor.java
public class DefaultConstructor {
    public static void main(String[] args) {
        System.out.println("=== Default Constructor ===\n");

        // Java provides default constructor when you write none
        SimpleClass obj = new SimpleClass();

        System.out.println("Object created with default constructor");
        System.out.println("number: " + obj.number);  // Default: 0
        System.out.println("text: " + obj.text);      // Default: null
        System.out.println("flag: " + obj.flag);      // Default: false

        // We can still set fields after construction
        obj.number = 42;
        obj.text = "Hello";
        obj.flag = true;

        System.out.println("\nAfter setting values:");
        System.out.println("number: " + obj.number);
        System.out.println("text: " + obj.text);
        System.out.println("flag: " + obj.flag);

        System.out.println("\n=== No Default If You Write One ===");
        // WithConstructor obj2 = new WithConstructor();  // Error!
        WithConstructor obj2 = new WithConstructor("Required");
        System.out.println("value: " + obj2.value);
    }
}

// Class without explicit constructor
class SimpleClass {
    int number;
    String text;
    boolean flag;

    // Java adds this automatically:
    // SimpleClass() { }
}

// Class with explicit constructor
class WithConstructor {
    String value;

    WithConstructor(String v) {  // No default constructor now!
        value = v;
    }
}

No-arg constructor sets fields to defaults: 0, null, false.

default constructor Java provides one if you write no constructors. Takes no parameters.

Parameterized constructor

Accept values to initialize fields.

ParameterizedConstructor.java
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}
public class ParameterizedConstructor {
    public static void main(String[] args) {
        System.out.println("=== Parameterized Constructor ===\n");

        // Create Person with required data
        int firstAge = ;
        String secondName = ;
        Person alice = new Person("Alice", firstAge);
        Person bob = new Person(secondName, 25);

        System.out.println("Created: " + alice.describe());
        System.out.println("Created: " + bob.describe());

        // No way to create incomplete Person!
        // Person invalid = new Person();  // Won't compile

        System.out.println("\n=== Benefits ===");
        System.out.println("✓ Object is fully initialized immediately");
        System.out.println("✓ Can't forget to set required fields");
        System.out.println("✓ Clear what data is needed");
    }
}

class Person {
    String name;
    int age;

    // Parameterized constructor
    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    String describe() {
        return name + " (age " + age + ")";
    }
}

Constructor name matches class name. No return type, not even void.

constructor Special method to initialize objects. Called automatically with `new`.

Constructor overloading

Multiple constructors for different creation scenarios.

ConstructorOverloading.java
public class ConstructorOverloading {
    public static void main(String[] args) {
        System.out.println("=== Constructor Overloading ===\n");

        // Multiple ways to create a Book
        Book book1 = new Book();
        System.out.println("1. " + book1.describe());

        Book book2 = new Book("1984");
        System.out.println("2. " + book2.describe());

        Book book3 = new Book("1984", "George Orwell");
        System.out.println("3. " + book3.describe());

        Book book4 = new Book("1984", "George Orwell", 328);
        System.out.println("4. " + book4.describe());

        System.out.println("\n=== Flexibility ===");
        System.out.println("Same class, 4 ways to construct!");
        System.out.println("Choose based on what data you have.");
    }
}

class Book {
    String title;
    String author;
    int pages;

    // Constructor 1: No arguments (defaults)
    Book() {
        title = "Untitled";
        author = "Unknown";
        pages = 0;
    }

    // Constructor 2: Title only
    Book(String title) {
        this.title = title;
        author = "Unknown";
        pages = 0;
    }

    // Constructor 3: Title and author
    Book(String title, String author) {
        this.title = title;
        this.author = author;
        pages = 0;
    }

    // Constructor 4: All fields
    Book(String title, String author, int pages) {
        this.title = title;
        this.author = author;
        this.pages = pages;
    }

    String describe() {
        String result = "\"" + title + "\" by " + author;
        if (pages > 0) {
            result += " (" + pages + " pages)";
        }
        return result;
    }
}

Provide several constructors for flexible object creation.

Constructor chaining

Call one constructor from another.

ConstructorChaining.java
public class ConstructorChaining {
    public static void main(String[] args) {
        System.out.println("=== Constructor Chaining with this() ===\n");

        // Create products with different constructors
        Product p1 = new Product();
        Product p2 = new Product("Laptop");
        Product p3 = new Product("Phone", 999.99);
        Product p4 = new Product("Tablet", 599.99, 50);

        System.out.println("1. " + p1.describe());
        System.out.println("2. " + p2.describe());
        System.out.println("3. " + p3.describe());
        System.out.println("4. " + p4.describe());

        System.out.println("\n=== Why Chain? ===");
        System.out.println("✓ Avoids code duplication");
        System.out.println("✓ Single place for initialization logic");
        System.out.println("✓ Easy to maintain");
    }
}

class Product {
    String name;
    double price;
    int stock;

    // Primary constructor - all parameters
    Product(String name, double price, int stock) {
        System.out.println("  [Primary constructor called]");
        this.name = name;
        this.price = price;
        this.stock = stock;
    }

    // Chain to primary with default stock
    Product(String name, double price) {
        this(name, price, 0);  // Calls primary constructor
        System.out.println("  [Two-arg constructor finished]");
    }

    // Chain to two-arg with default price
    Product(String name) {
        this(name, 0.0);  // Calls two-arg constructor
        System.out.println("  [One-arg constructor finished]");
    }

    // Chain to one-arg with default name
    Product() {
        this("Unknown");  // Calls one-arg constructor
        System.out.println("  [No-arg constructor finished]");
    }

    String describe() {
        return name + " ($" + price + ", " + stock + " in stock)";
    }
}

this(args) calls another constructor. Must be first statement.

this() Call another constructor: `this(args)`. Avoids duplicating initialization code.

Validate in constructor

Reject invalid data at creation time.

Validation.java
public class Validation {
    public static void main(String[] args) {
        System.out.println("=== Validation in Constructors ===\n");

        // Valid accounts
        Account acc1 = new Account("ACC001", 100.0);
        System.out.println("Created: " + acc1.describe());

        Account acc2 = new Account("ACC002", 0.0);
        System.out.println("Created: " + acc2.describe());

        System.out.println("\n=== Invalid Attempts ===");

        // Invalid: null ID
        try {
            new Account(null, 100.0);
        } catch (IllegalArgumentException e) {
            System.out.println("Rejected null ID: " + e.getMessage());
        }

        // Invalid: empty ID
        try {
            new Account("", 100.0);
        } catch (IllegalArgumentException e) {
            System.out.println("Rejected empty ID: " + e.getMessage());
        }

        // Invalid: negative balance
        try {
            new Account("ACC003", -50.0);
        } catch (IllegalArgumentException e) {
            System.out.println("Rejected negative: " + e.getMessage());
        }

        System.out.println("\n=== Benefit ===");
        System.out.println("Invalid objects can NEVER be created!");
    }
}

class Account {
    final String id;
    double balance;

    Account(String id, double balance) {
        // Validate ID
        if (id == null || id.isEmpty()) {
            throw new IllegalArgumentException("ID cannot be null or empty");
        }

        // Validate balance
        if (balance < 0) {
            throw new IllegalArgumentException("Balance cannot be negative");
        }

        // All validations passed - initialize
        this.id = id;
        this.balance = balance;
    }

    String describe() {
        return "Account " + id + ": $" + balance;
    }
}

Throw exceptions for invalid arguments. Prevent invalid objects from existing.

Exercise: CompleteExample.java

Create a complete class with multiple constructors and validation