Learn / Programming / Java / Classes and Objects

Java · Lesson 4 of 6

Classes and Objects

Fields, constructors, methods, and encapsulation with private.

  • Intermediate
  • 18 min read
  • 3 objectives

Before this lessonLesson 3: Control Flow

What you will learn

  • Define a class with fields
  • Write a constructor
  • Add getters/setters

Java is object-oriented from the ground up. A class describes the shape of something (its fields) and what it can do (its methods). An object is a concrete instance created with new. Good classes hide their internal data and expose a small, safe set of operations. That idea is called encapsulation.

Objects model real things

Java is built around object-oriented programming. Rather than a long list of separate variables and functions, you describe a kind of thing once as a class (its data and its abilities) and then create as many objects from it as you need. A BankAccount class describes what every account has (an owner, a balance) and can do (deposit, withdraw). Each customer's account is a separate object with its own numbers.

A class with a constructor

A constructor has the same name as the class and no return type. It runs when you call new and sets the object up. Marking fields private stops outside code from changing them directly.

public class BankAccount {
    private final String owner;
    private double balance;

    public BankAccount(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
    }

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

    public double getBalance() { return balance; }
    public String getOwner()   { return owner; }
}

this refers to the current object, and is needed here to tell the field this.owner apart from the parameter owner.

Using the class

BankAccount acct = new BankAccount("Amar", 100);
acct.deposit(50);
System.out.println(acct.getOwner() + ": " + acct.getBalance());
Output
Amar: 150.0

Static versus instance

Instance members belong to each object; static members belong to the class and are shared. Math.sqrt(9) is a static method: you call it on the class, not on an object.

Inheritance and interfaces

A subclass extends one parent class. An interface is a contract of methods that a class promises to provide, and a class may implements many of them. Prefer interfaces when you want different classes to be used interchangeably.

interface Shape {
    double area();
}

class Circle implements Shape {
    private final double r;
    Circle(double r) { this.r = r; }
    public double area() { return Math.PI * r * r; }
}

class Square implements Shape {
    private final double s;
    Square(double s) { this.s = s; }
    public double area() { return s * s; }
}

Shape[] shapes = { new Circle(1), new Square(2) };
for (Shape sh : shapes) {
    System.out.printf("%.2f%n", sh.area());
}
Output
3.14
4.00

Calling sh.area() runs the right version for each object. That is polymorphism: one call, many behaviors.

A class, an object, and encapsulation

class BankAccount {
    private final String owner;
    private double balance;

    BankAccount(String owner, double balance) {
        this.owner = owner;
        this.balance = balance;
    }

    void deposit(double amount) {
        if (amount <= 0) throw new IllegalArgumentException("amount must be positive");
        balance += amount;
    }

    double getBalance() { return balance; }
    String getOwner() { return owner; }
}

public class Main {
    public static void main(String[] args) {
        BankAccount a = new BankAccount("Ada", 100);
        BankAccount b = new BankAccount("Linus", 50);
        a.deposit(25);
        System.out.println(a.getOwner() + ": " + a.getBalance());
        System.out.println(b.getOwner() + ": " + b.getBalance());
    }
}
Output
Ada: 125.0
Linus: 50.0
  • private fields can only be touched from inside the class. This is encapsulation: outsiders must go through methods, so the class can enforce its rules (no negative deposits).
  • The constructor has the class name and no return type; it runs when you write new BankAccount(...).
  • this refers to the object being built or used, and disambiguates fields from parameters.
  • Each new creates an independent object: depositing into a never changes b.

Inheritance and polymorphism

class Animal {
    String speak() { return "..."; }
}

class Dog extends Animal {
    @Override
    String speak() { return "Woof"; }
}

class Cat extends Animal {
    @Override
    String speak() { return "Meow"; }
}

public class Main {
    public static void main(String[] args) {
        Animal[] pets = { new Dog(), new Cat(), new Animal() };
        for (Animal p : pets) {
            System.out.println(p.speak());
        }
    }
}
Output
Woof
Meow
...

The loop only knows about Animal, yet each object answers in its own way. That is polymorphism: the same call, different behaviour depending on the real object. It lets you add a new kind of animal without changing the loop.

Interfaces: promises about behaviour

interface Shape {
    double area();
}

record Circle(double r) implements Shape {
    public double area() { return Math.PI * r * r; }
}

record Rect(double w, double h) implements Shape {
    public double area() { return w * h; }
}

public class Main {
    public static void main(String[] args) {
        Shape[] shapes = { new Circle(1), new Rect(3, 4) };
        for (Shape s : shapes) {
            System.out.printf("%.2f%n", s.area());
        }
    }
}
Output
3.14
12.00

Key takeaways

  • A class is a blueprint; new makes independent objects from it.
  • Keep fields private and expose behaviour through methods (encapsulation).
  • Subclasses extend and @Override; interfaces declare what a class can do.
  • Polymorphism lets code work with the general type while objects behave as their real type.
// Write your solution here
Up next · Lesson 5Collections FrameworkArrayList, HashMap, and when to pick each.