LearnFrenzy
Sign in Take a free test

Classes and Objects · Lesson 20 of 42

Classes, Objects and Constructors

5 min read Updated Nov 7, 2026 Saurabh Samir

Java is an object-oriented language: real programs are built from objects that bundle data with the code that works on it. A bank account knows its balance and how to deposit; an order knows its items and how to calculate its total. A class is the blueprint; objects are the things built from it.

In this lesson

  • Defining a class with fields and methods
  • Creating objects with new and how they live in memory
  • Constructors, overloading and this
  • Default values and toString()

A class and its objects

public class Main {
    public static void main(String[] args) {
        BankAccount a = new BankAccount();    // create an object
        a.owner = "Asha";
        a.deposit(5000);

        BankAccount b = new BankAccount();
        b.owner = "Ben";
        b.deposit(1200);

        System.out.println(a.summary());
        System.out.println(b.summary());
    }
}

class BankAccount {
    String owner;          // fields: the object's data
    double balance;

    void deposit(double amount) {      // methods: what it can do
        balance += amount;
    }

    String summary() {
        return owner + ": ₹" + balance;
    }
}

Output

Asha: ₹5000.0
Ben: ₹1200.0

One class, many objects

class BankAccount (blueprint)

  • object aowner "Asha", balance 5000.0
  • object bowner "Ben", balance 1200.0

Several classes in one file

To keep examples short, this course puts small helper classes in the same file as Main. Only one class per file may be public, and its name must match the file. Keep Main first: java Main.java runs the first class in the file. In real projects, give every class its own file.

Each object has its own copy of the fields. Methods without static are instance methods: they run on a particular object (a.deposit(...)) and use that object's fields.

Objects live on the heap

new BankAccount() creates the object on the heap and returns a reference to it. The variable a (on the stack) stores that reference.

Stack and heap

  1. Stack: variable aholds a reference (an address)
  2. Heap: BankAccount objectowner → "Asha", balance = 5000.0
  3. Garbage collectorfrees objects that no reference points to any more
public class Main {
    public static void main(String[] args) {
        Counter c1 = new Counter();
        Counter c2 = c1;          // same object, two references
        c2.value = 10;
        System.out.println(c1.value);
        System.out.println(c1 == c2);
        Counter c3 = new Counter();
        System.out.println(c3.value + " " + (c1 == c3));   // fields get default values
    }
}

class Counter {
    int value;
}

Output

10
true
0 false

Fields get default values (0, false, null), unlike local variables.

Constructors

Setting fields one by one after new is error-prone – you could forget one. A constructor runs automatically when an object is created and makes sure it starts in a valid state. It has the class's name and no return type.

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("Ira", 21, 8.9);
        Student s2 = new Student("Jay", 22);
        System.out.println(s1);       // println calls toString()
        System.out.println(s2);
    }
}

class Student {
    String name;
    int rollNo;
    double cgpa;

    Student(String name, int rollNo, double cgpa) {
        this.name = name;         // this.name = the field, name = the parameter
        this.rollNo = rollNo;
        this.cgpa = cgpa;
    }

    Student(String name, int rollNo) {   // overloaded constructor
        this(name, rollNo, 0.0);          // call the other constructor
    }

    @Override
    public String toString() {
        return "Student{" + rollNo + ", " + name + ", " + cgpa + "}";
    }
}

Output

Student{21, Ira, 8.9}
Student{22, Jay, 0.0}
  • this refers to the current object. this.name = name copies the parameter into the field with the same name.
  • this(...) calls another constructor of the same class – it must be the first statement.
  • Overriding toString() controls how the object prints – always worth doing for debugging.

Common mistake: the disappearing default constructor

If you write no constructor, Java adds an empty one, so new Student() works. As soon as you write any constructor, that free default disappears and new Student() no longer compiles – add a no-argument constructor yourself if you need one.

Common mistake: forgetting this

Writing name = name; in the constructor assigns the parameter to itself; the field stays null. Use this.name = name;.

Validation in the constructor

public class Main {
    public static void main(String[] args) {
        Product ok = new Product("Keyboard", 899);
        System.out.println(ok.name + " ₹" + ok.price);
        try {
            new Product("Mouse", -10);
        } catch (IllegalArgumentException e) {
            System.out.println("Rejected: " + e.getMessage());
        }
    }
}

class Product {
    final String name;
    final double price;

    Product(String name, double price) {
        if (name == null || name.isBlank()) throw new IllegalArgumentException("name required");
        if (price < 0) throw new IllegalArgumentException("price cannot be negative");
        this.name = name;
        this.price = price;
    }
}

Output

Keyboard ₹899.0
Rejected: price cannot be negative

An object that can only be created in a valid state saves you from checking it everywhere else.

Practice

Try it yourself

  1. Create a Rectangle class with width, height, a constructor, area() and perimeter().

    Show solution
    public class Main {
        public static void main(String[] args) {
            Rectangle r = new Rectangle(4, 3);
            System.out.println(r.area() + " " + r.perimeter());
        }
    }
    
    class Rectangle {
        double width, height;
    
        Rectangle(double width, double height) {
            this.width = width;
            this.height = height;
        }
    
        double area() { return width * height; }
        double perimeter() { return 2 * (width + height); }
    }

    Output

    12.0 14.0
  2. Give Rectangle a second constructor that builds a square from one side, using this(...).

    Show solution
    public class Main {
        public static void main(String[] args) {
            System.out.println(new Rectangle(5).area());
        }
    }
    
    class Rectangle {
        double width, height;
        Rectangle(double width, double height) { this.width = width; this.height = height; }
        Rectangle(double side) { this(side, side); }
        double area() { return width * height; }
    }

    Output

    25.0

Quick check

Does a constructor have a return type?

No – not even void. A method with a return type and the class's name is just an oddly named method.

What does this(...) do and where must it appear?

It calls another constructor of the same class and must be the first statement.

After Counter b = a; how many Counter objects exist?

One – both variables reference the same object.

Summary

  • A class defines fields and methods; new creates objects on the heap and returns references.
  • Constructors initialise objects in a valid state; this means the current object.
  • Writing any constructor removes the default one; override toString() for readable output.

Finished this lesson?

Mark it complete to track your progress, then carry on with the next lesson.

Next lesson

Popular