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.
| Aspect | Procedural Programming | Object-Oriented Programming |
|---|---|---|
| Focus | Function (feature) centric | Object (data + feature) centric |
| Structure | Executes sequentially from top to bottom | Objects communicate by sending messages |
| Reuse | Reuse at the function level | Reuse at the class/object level |
| Maintenance | Complexity explodes as scale grows | Modularity minimizes the impact of changes |
| Example languages | C, Pascal, FORTRAN | Java, 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.
- Encapsulation: Groups data and methods together and restricts external access to protect data.
- Inheritance: Inherits properties and features of an existing class, enabling code reuse and extension.
- Polymorphism: The same code behaves differently depending on the actual type of the object.
- 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)
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: 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
}
}
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 Method | Target | Result |
|---|---|---|
== | 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
| Aspect | Member Variable (Field) | Local Variable |
|---|---|---|
| Declaration location | Inside a class (outside methods) | Inside a method, constructor, or block |
| Created | When the object is created | When the declaration statement is executed |
| Destroyed | When the object is garbage-collected | When the block ({}) ends |
| Default value | Auto-initialized to type default | None (must initialize manually) |
| Storage | Heap | Stack |
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
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
| Concept | Description |
|---|---|
| Class | Blueprint for creating objects (fields + methods) |
| Object / Instance | An entity created from a class (exists on heap memory) |
new operator | Allocates object space on heap + calls constructor |
| Reference variable | A variable that stores the address of an object on the heap |
== | Reference (address) comparison |
equals() | Content comparison (requires override) |
| Member variable | Declared inside a class, auto-initialized, stored on heap |
| Local variable | Declared inside a method, must be manually initialized, stored on stack |