Skip to main content

6.1 Classes and Objects

Java is a true Object-Oriented Programming (OOP) language. The heart of object-oriented programming is modeling real-world objects and concepts as "objects" in a computer program.

1. Procedural vs Object-Oriented Programming

To understand OOP, let's first look at the difference from the previous paradigm, Procedural Programming.

AspectProcedural ProgrammingObject-Oriented Programming
FocusFunction (feature) centricObject (data + feature) centric
StructureExecutes sequentially from top to bottomObjects communicate by sending messages
ReuseReuse at the function levelReuse at the class/object level
MaintenanceComplexity explodes as scale growsModularity minimizes the impact of changes
Example languagesC, Pascal, FORTRANJava, C++, Python, C#

Procedural programming suits small programs, but in large-scale projects with tens of thousands of lines, interdependencies grow explosively, making maintenance difficult. OOP was created to solve this problem.

2. The Four Pillars of OOP

Object-oriented design is built on four core principles.

  1. Encapsulation: Groups data and methods together and restricts external access to protect data.
  2. Inheritance: Inherits properties and features of an existing class, enabling code reuse and extension.
  3. Polymorphism: The same code behaves differently depending on the actual type of the object.
  4. Abstraction: Hides complex internal implementation and exposes only the essential interface.

These principles maximize reusability, flexibility, and maintainability of code.

3. Defining Class and Object

Class — The Blueprint

  • Definition: A template or blueprint for creating objects
  • Characteristic: Does not occupy memory (no physical existence until instantiated)
  • Analogy: A cookie cutter, a TV blueprint, a car design document

Object / Instance — The Real Thing

  • Definition: An actual entity created from a class, physically allocated in memory (heap)
  • Characteristic: Each has its own independent state (data)
  • Analogy: Individual cookies made from the same cutter (same template, but each is distinct)
Instantiation

The process of creating an object from a class is called instantiation, and the resulting object is called an instance of that class. "Instance" and "object" are used almost interchangeably.

4. Class Declaration Syntax

A class is composed of attributes (fields) and behaviors (methods).

// accessModifier class ClassName {
// type fieldName; // member variable (attribute)
// returnType methodName() { ... } // method (behavior)
// }

public class Car {
// === Member variables (fields) ===
String brand; // brand
String color; // color
int speed; // current speed
int fuel; // fuel level

// === Methods (behavior) ===
void accelerate(int amount) {
speed += amount;
fuel -= amount / 10;
System.out.println("Accelerating! Current speed: " + speed + " km/h");
}

void brake() {
if (speed > 0) {
speed -= 20;
if (speed < 0) speed = 0;
}
System.out.println("Braking! Current speed: " + speed + " km/h");
}

void displayInfo() {
System.out.println("=== Vehicle Info ===");
System.out.println("Brand: " + brand);
System.out.println("Color: " + color);
System.out.println("Speed: " + speed + " km/h");
System.out.println("Fuel: " + fuel + " L");
}
}

5. Creating Objects: new Operator and Heap Memory

Objects are created using the new operator. new allocates space for the object in the Heap memory and returns its address.

// Step 1: Declare a reference variable (creates variable space only on the stack)
Car myCar;

// Step 2: Create the object and assign its address to the reference variable
// (allocates Car object space in heap memory)
myCar = new Car();

// Declaration and creation in one line
Car yourCar = new Car();
Stack vs Heap Memory
  • Stack: Stores reference variables (address values). Created when a method is called, automatically destroyed when it returns.
  • Heap: Stores actual objects (data). Created with new, cleaned up by the garbage collector (GC).

6. Reference Variables and Objects

A reference variable does not store the object itself — it stores the heap memory address where the object lives.

public class ReferenceExample {
public static void main(String[] args) {
Car car1 = new Car(); // create object A
Car car2 = new Car(); // create object B
Car car3 = car1; // car3 references the same object A as car1!

car1.brand = "Hyundai";
car3.brand = "Kia"; // car3 == car1, so car1.brand also becomes "Kia"

System.out.println(car1.brand); // Kia (same object!)
System.out.println(car3.brand); // Kia

// car2 is independent
car2.brand = "BMW";
System.out.println(car2.brand); // BMW
}
}
Reference Copy vs Value Copy

car3 = car1 does not copy the object — it copies the address (reference). Both variables now point to the same object. Always keep this in mind!

7. Comparing Objects: == vs equals()

public class CompareExample {
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
Car car3 = car1;

car1.brand = "Hyundai";
car2.brand = "Hyundai"; // same content, but different objects

// == operator: compares references (addresses)
System.out.println(car1 == car2); // false (different objects)
System.out.println(car1 == car3); // true (same object reference)

// String: use equals() to compare content
String s1 = new String("Java");
String s2 = new String("Java");
System.out.println(s1 == s2); // false (different objects)
System.out.println(s1.equals(s2)); // true (same content)
}
}
Comparison MethodTargetResult
==Reference (address)true if pointing to the same object
equals()Content (data)true if content is the same (requires override)

8. Member Variables (Fields) vs Local Variables

AspectMember Variable (Field)Local Variable
Declaration locationInside a class (outside methods)Inside a method, constructor, or block
CreatedWhen the object is createdWhen the declaration statement is executed
DestroyedWhen the object is garbage-collectedWhen the block ({}) ends
Default valueAuto-initialized to type defaultNone (must initialize manually)
StorageHeapStack
public class VariableExample {
// Member variables (automatically initialized to defaults)
int memberInt; // 0
double memberDouble; // 0.0
boolean memberBool; // false
String memberStr; // null

void showDefaultValues() {
System.out.println("int default: " + memberInt);
System.out.println("double default: " + memberDouble);
System.out.println("boolean default: " + memberBool);
System.out.println("String default: " + memberStr);
}

void localVarExample() {
int localVar; // declaration only
// System.out.println(localVar); // Compile error! Cannot use uninitialized local variable
localVar = 10; // can use after initialization
System.out.println("Local variable: " + localVar);
}
}

9. Practical Example: Full Car Class Implementation

Designing a fully functional Car class.

public class Car {
// Member variables (fields)
String brand;
String model;
String color;
int speed; // current speed (km/h)
int fuel; // fuel level (L)
boolean isOn; // engine status

// Start engine
void start() {
if (isOn) {
System.out.println(brand + " " + model + ": Engine is already running.");
return;
}
if (fuel <= 0) {
System.out.println("Cannot start: no fuel!");
return;
}
isOn = true;
System.out.println(brand + " " + model + ": Vroom! Engine started!");
}

// Stop engine
void stop() {
if (!isOn) {
System.out.println("Engine is already off.");
return;
}
isOn = false;
speed = 0;
System.out.println(brand + " " + model + ": Engine stopped.");
}

// Accelerate
void accelerate(int amount) {
if (!isOn) {
System.out.println("Please start the engine first!");
return;
}
speed += amount;
fuel -= amount / 10;
System.out.printf("Accelerated +%d km/h -> Current speed: %d km/h, Fuel: %d L%n",
amount, speed, fuel);
}

// Brake
void brake(int amount) {
speed = Math.max(0, speed - amount);
System.out.printf("Braked -%d km/h -> Current speed: %d km/h%n", amount, speed);
}

// Refuel
void refuel(int amount) {
fuel += amount;
System.out.println("Refueled " + amount + " L. Total fuel: " + fuel + " L");
}

// Display status
void displayStatus() {
System.out.println("============================");
System.out.println("Vehicle: " + brand + " " + model);
System.out.println("Color: " + color);
System.out.println("Engine: " + (isOn ? "ON" : "OFF"));
System.out.println("Speed: " + speed + " km/h");
System.out.println("Fuel: " + fuel + " L");
System.out.println("============================");
}
}

// Test class
public class CarTest {
public static void main(String[] args) {
// Create objects
Car sonata = new Car();
sonata.brand = "Hyundai";
sonata.model = "Sonata";
sonata.color = "White";
sonata.fuel = 50;

Car bmw = new Car();
bmw.brand = "BMW";
bmw.model = "520d";
bmw.color = "Black";
bmw.fuel = 60;

// Drive the Sonata
sonata.start();
sonata.accelerate(60);
sonata.accelerate(40);
sonata.brake(30);
sonata.displayStatus();

// Drive the BMW
bmw.start();
bmw.accelerate(100);
bmw.displayStatus();
}
}

Output:

Hyundai Sonata: Vroom! Engine started!
Accelerated +60 km/h -> Current speed: 60 km/h, Fuel: 44 L
Accelerated +40 km/h -> Current speed: 100 km/h, Fuel: 40 L
Braked -30 km/h -> Current speed: 70 km/h
============================
Vehicle: Hyundai Sonata
Color: White
Engine: ON
Speed: 70 km/h
Fuel: 40 L
============================

10. Relationship Between Class and Object

// One class can create many independent objects
Car car1 = new Car(); // object 1
Car car2 = new Car(); // object 2 (completely independent of car1)
Car car3 = new Car(); // object 3

car1.speed = 100;
car2.speed = 60;
car3.speed = 0;

// Each object has its own independent state (speed)
System.out.println(car1.speed); // 100
System.out.println(car2.speed); // 60
System.out.println(car3.speed); // 0
The Real Power of OOP

A single class can create thousands of independent objects. Each object shares the same structure (fields, methods) but maintains its own distinct state (data). This is the core appeal of OOP.

Summary

ConceptDescription
ClassBlueprint for creating objects (fields + methods)
Object / InstanceAn entity created from a class (exists on heap memory)
new operatorAllocates object space on heap + calls constructor
Reference variableA variable that stores the address of an object on the heap
==Reference (address) comparison
equals()Content comparison (requires override)
Member variableDeclared inside a class, auto-initialized, stored on heap
Local variableDeclared inside a method, must be manually initialized, stored on stack