Phase 2 · Object-Oriented JavaModule 8~45 min read

Object-Oriented Programming Fundamentals

The heart of Java: classes, objects, constructors, encapsulation, and the static/final keywords.

What you'll learn

This is the module where Java clicks. Object-oriented programming (OOP) is how Java models the world: as objects that bundle data and behaviour together. Master it and everything from Android apps to enterprise systems opens up.

By the end you'll be able to:

  • Write classes with fields and methods, and create objects with new
  • Initialise objects with constructors (including overloaded ones)
  • Use this to refer to the current object
  • Protect data with encapsulation, access modifiers, and getters/setters
  • Share data and behaviour across all objects with static
  • Lock values, methods, and classes with final

Classes & objects

Procedural code (what you've written so far) is a list of instructions. OOP organises code around objects — self-contained units that hold state (data) and behaviour (methods). A class is the blueprint; an object is a concrete thing built from it.

Class vs object

Class — the blueprint

Dog

Defines what every dog has (name, age) and does (bark).

→
Rex (object)
Buddy (object)
Max (object)
One class can produce any number of independent objects.

A class's fields describe what an object has; its methods describe what it does. You bring an object to life with the new keyword:

Dog.java
public class Dog {
    String name;              // fields = state
    int age;

    void bark() {             // method = behaviour
        System.out.println(name + " says Woof!");
    }

    public static void main(String[] args) {
        Dog d = new Dog();    // create an object with 'new'
        d.name = "Rex";
        d.age = 3;
        d.bark();
        System.out.println(d.name + " is " + d.age);
    }
}

Constructors

Setting each field after creation (like d.name = ...) is tedious and error-prone. A constructor is a special method — same name as the class, no return type — that runs the moment you call new, letting you set up the object in one step. If you don't write one, Java gives you a default (no-argument) constructor for free.

Dog.java
public class Dog {
    String name;
    int age;

    Dog(String name, int age) {   // constructor: runs on 'new'
        this.name = name;
        this.age = age;
    }

    Dog(String name) {            // overloaded constructor
        this(name, 0);            // calls the other one
    }

    public static void main(String[] args) {
        Dog a = new Dog("Rex", 3);
        Dog b = new Dog("Pup");   // age defaults to 0
        System.out.println(a.name + ", " + a.age);
        System.out.println(b.name + ", " + b.age);
    }
}

Note

You can provide several constructors with different parameters (constructor overloading). One constructor can call another with this(...) to avoid repeating setup code.

The this keyword

Inside a method or constructor, this refers to the current object. Its most common use is disambiguating a field from a parameter with the same name — this.name = name means "set this object's name field to the name parameter." It also lets one constructor call another with this(...).

Encapsulation & access modifiers

Encapsulation means hiding an object's internal data and exposing only a controlled interface. You mark fields private so nothing outside the class can touch them directly, then provide getters and setters to read and change them on your terms — validating input, enforcing rules, keeping the object always valid.

Encapsulation

public methods — the controlled interface

deposit()getBalance()

private fields — hidden state

balance

The outside world can only touch balance through your methods — so you control the rules.

BankAccount.java
public class BankAccount {
    private double balance;              // hidden from outside

    public double getBalance() {         // read access
        return balance;
    }

    public void deposit(double amount) { // write access WITH rules
        if (amount > 0) {
            balance += amount;
        }
    }

    public static void main(String[] args) {
        BankAccount acc = new BankAccount();
        acc.deposit(100);
        acc.deposit(-50);                // rejected by validation
        System.out.println(acc.getBalance());
    }
}

Four access modifiers control visibility, from most open to most closed:

  • public — accessible from anywhere
  • protected — accessible in the same package and by subclasses
  • (default / package-private) — accessible only in the same package
  • private — accessible only inside the same class

Tip

The golden rule: make fields private by default, and expose behaviour through methods. This keeps objects in control of their own state — the heart of good OOP.

static fields & methods

A static member belongs to the class itself, not to any single object — so it's shared by every instance. A static field is perfect for a shared counter or a constant; a static method (like Math.max) is called on the class without creating an object.

static vs instance

Instance members

Belong to each object. Every Dog has its own name. Accessed via the object: rex.name.

static members

Belong to the class, shared by all objects. Accessed via the class: Dog.count.

Counter.java
public class Counter {
    static int count = 0;    // shared by ALL Counters
    int id;                  // unique per object

    Counter() {
        count++;
        id = count;
    }

    public static void main(String[] args) {
        new Counter();
        new Counter();
        Counter third = new Counter();
        System.out.println("I am object #" + third.id);
        System.out.println("Total created: " + Counter.count);
    }
}

Note

main is static for exactly this reason — the JVM can call it without first creating an object. Static initialization blocks (static { ... }) run once when the class first loads, handy for one-time setup.

The final keyword

final means "this can't change," and it works on three things:

  • final variable — a constant; can be assigned only once
  • final method — cannot be overridden by a subclass (Module 9)
  • final class — cannot be extended at all (e.g. String is final)

Note

Marking things final when they shouldn't change makes your intent clear and prevents accidental modification — a small habit that pays off in large programs.

Recap & quick check

Key takeaways

  • A class is a blueprint; an object is a concrete instance created with new.
  • Fields hold state, methods define behaviour, constructors initialise the object.
  • this refers to the current object — great for field/parameter name clashes.
  • Encapsulation = private fields + public getters/setters that enforce your rules.
  • static members belong to the class and are shared; final locks a value, method, or class.

Quick check

1. What is the relationship between a class and an object?

2. When does a constructor run?

3. Why make fields private and expose getters/setters?

4. A static field is…

5. What does 'final' do to a variable?

Brilliant — you've crossed into object-oriented thinking. Next up: Module 9 — Inheritance & Polymorphism, where classes start building on one another.