Stage 2: Object-oriented programming, lesson 1 of 10

Classes, objects and constructors

Beginner3 min readall versions
Explain it forThe essentials plus production detail and pitfalls.

A class defines state (fields) and behaviour (methods). An object is an instance of a class, created with new.

A constructor runs when the object is created and has no return type. If you write no constructor, Java adds a no-argument default one. Constructors can call each other with this(...).

this refers to the current object. static fields are shared by every instance of the class.

Since Java 25, flexible constructor bodies let you run validation statements before calling super(...) or this(...).

Classes and objects

A class is a blueprint; an object is one thing built from it. new creates the object on the heap and returns a reference to it. Several variables can point at the same object.

Java
Car a = new Car("Nexon");
Car b = a;              // same object, two references
b.rename("Harrier");
System.out.println(a.name());   // Harrier

Fields and methods: state and behaviour

Fields hold an object's state; methods define its behaviour and usually read or change that state. Keep fields private and expose meaningful methods (deposit, withdraw) rather than raw setters.

Java
public class Account {
    private long balancePaise;

    public void deposit(long paise) {
        if (paise <= 0) throw new IllegalArgumentException("amount must be positive");
        balancePaise += paise;
    }

    public long balance() { return balancePaise; }
}

Constructors and constructor chaining

A constructor has the class name and no return type. If you write none, Java adds a no-argument one. Overload constructors for different ways to create an object, and chain them with this(...) so the logic lives in one place.

Java
public class Course {
    private final String title;
    private final int priceInr;

    public Course(String title) {
        this(title, 0);                     // free by default
    }

    public Course(String title, int priceInr) {
        if (title == null || title.isBlank()) throw new IllegalArgumentException("title required");
        this.title = title;
        this.priceInr = priceInr;
    }
}

The this keyword

this is the current object. Use it to tell a field apart from a parameter with the same name, to pass the current object to another method, or to call another constructor (this(...)).

Initialisation order

When an object is created: static fields and static blocks run once when the class first loads; then, for each object, field initialisers and instance blocks run in order, then the constructor body. With inheritance, the parent's part is built first.

Java
class Demo {
    static { System.out.println("1. class loaded (once)"); }
    private int x = log("2. field initialiser");
    { System.out.println("3. instance block"); }
    Demo() { System.out.println("4. constructor"); }
    static int log(String s) { System.out.println(s); return 0; }
}

Encapsulation, getters and setters

Hide fields (private) and control access through methods, so you can validate input and change the internals later without breaking callers. Don't add a setter for everything; many fields should be set once, in the constructor. For plain data carriers, use a record.

Static members vs instance members

Static fields are shared by all objects of the class (a counter, a constant); instance fields belong to each object. See the lesson on static and final for the details and pitfalls.

Example

Java
public class Account {
    private final String owner;
    private double balance;
    private static int count = 0;          // shared by all accounts

    public Account(String owner) {
        this(owner, 0);                    // constructor chaining
    }

    public Account(String owner, double opening) {
        if (opening < 0) throw new IllegalArgumentException("Negative opening balance");
        this.owner = owner;
        this.balance = opening;
        count++;
    }

    public void deposit(double amount) { balance += amount; }
    public double getBalance()         { return balance; }
}

Account acc = new Account("Meera", 500);
acc.deposit(250);

Common mistake

Adding a constructor with parameters removes the automatic no-arg constructor. Frameworks like JPA and Jackson often need one, so add it back (it can be protected).

Under the hood

new allocates memory (usually from a thread-local allocation buffer, which is very cheap), zeroes the fields, runs field initializers and then the constructor chain from Object downwards. If the JIT proves an object never escapes a method, it may skip the heap allocation entirely (escape analysis).

Check yourself

You declare only Account(String owner). What happens to new Account()?

How this connects

Part of Java from zero.

Was this lesson helpful?

Finished reading? Mark it complete to track your progress.