Skip to content

Java Intermediate Guide

Mattscreative edited this page Mar 9, 2026 · 1 revision

Java Intermediate Guide - Object-Oriented Programming

Table of Contents


Introduction to OOP

Object-Oriented Programming (OOP) is a way of organizing code that treats data and functions as objects. Think of objects as real-world things:

  • Car - has properties (color, speed) and actions (drive, brake)
  • BankAccount - has properties (balance, owner) and actions (deposit, withdraw)
  • Player - has properties (name, score) and actions (jump, shoot)

The Four Pillars of OOP

Pillar Meaning Example
Encapsulation Bundling data and methods together A Car object contains its speed and drive() method
Inheritance Child classes inherit from parents ElectricCar extends Car
Polymorphism Same action, different behavior All shapes have area(), but each calculates differently
Abstraction Hiding complexity You drive a car without knowing how the engine works

Classes and Objects

A class is a blueprint - it defines what an object will look like. An object is an actual thing created from that blueprint.

Creating a Class

public class Car {
    // Properties (also called fields or attributes)
    String color;
    String make;
    String model;
    int speed;
    
    // Methods (actions the car can do)
    public void drive() {
        System.out.println("The car is driving!");
    }
    
    public void brake() {
        speed = 0;
        System.out.println("Car stopped!");
    }
    
    public void displayInfo() {
        System.out.println(color + " " + make + " " + model);
    }
}

Creating Objects

public class Main {
    public static void main(String[] args) {
        // Create an object from the Car class
        Car myCar = new Car();
        
        // Set properties
        myCar.color = "Red";
        myCar.make = "Toyota";
        myCar.model = "Camry";
        myCar.speed = 0;
        
        // Call methods
        myCar.displayInfo();  // Red Toyota Camry
        myCar.drive();        // The car is driving!
        myCar.brake();        // Car stopped!
    }
}

Class vs Object

Class Object
Blueprint Actual thing
Defines properties and methods Has actual values
One class, many objects Created from a class

Constructors

A constructor is a special method that runs when you create an object. It's used to set up the object with initial values.

Default Constructor

public class Person {
    String name;
    int age;
    
    // Default constructor (no parameters)
    public Person() {
        name = "Unknown";
        age = 0;
    }
    
    public static void main(String[] args) {
        Person p = new Person();  // Calls constructor
        System.out.println(p.name);  // Unknown
    }
}

Parameterized Constructor

public class Person {
    String name;
    int age;
    
    // Constructor with parameters
    public Person(String name, int age) {
        this.name = name;    // "this" refers to the current object
        this.age = age;
    }
    
    public static void main(String[] args) {
        Person alice = new Person("Alice", 25);
        System.out.println(alice.name);  // Alice
        System.out.println(alice.age);   // 25
    }
}

Multiple Constructors (Overloading)

public class Person {
    String name;
    int age;
    
    // No-arg constructor
    public Person() {
        this.name = "Unknown";
        this.age = 0;
    }
    
    // Constructor with name only
    public Person(String name) {
        this.name = name;
        this.age = 0;
    }
    
    // Constructor with all parameters
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Encapsulation

Encapsulation means protecting data by controlling how it's accessed. You hide the internal details and only expose what's necessary.

The Problem Without Encapsulation

// BAD - anyone can change these values directly!
public class BankAccount {
    public double balance;  // Public - anyone can change it!
}

// In main:
BankAccount account = new BankAccount();
account.balance = -1000000;  // Invalid! But possible without encapsulation

The Solution: Private Fields + Getters/Setters

public class BankAccount {
    // Private - can't access directly from outside
    private double balance;
    private String accountNumber;
    
    // Constructor
    public BankAccount(String accountNumber, double initialBalance) {
        this.accountNumber = accountNumber;
        // Validate initial balance
        if (initialBalance >= 0) {
            this.balance = initialBalance;
        } else {
            this.balance = 0;
        }
    }
    
    // Getter - read-only access
    public double getBalance() {
        return balance;
    }
    
    // Setter - controlled modification
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("Deposited: " + amount);
        } else {
            System.out.println("Invalid deposit amount!");
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("Withdrawn: " + amount);
        } else {
            System.out.println("Invalid withdrawal!");
        }
    }
}

Using Encapsulation

public class Main {
    public static void main(String[] args) {
        BankAccount account = new BankAccount("12345", 1000);
        
        // Can't do this anymore:
        // account.balance = -1000000;  // ERROR!
        
        // Must use methods:
        account.deposit(500);      // Deposited: 500.0
        account.withdraw(200);     // Withdrawn: 200.0
        System.out.println(account.getBalance());  // 1300.0
    }
}

Inheritance

Inheritance allows a class to inherit properties and methods from another class. The child class gets everything from the parent!

Basic Inheritance

// Parent class (Superclass)
public class Animal {
    String name;
    int age;
    
    public void eat() {
        System.out.println(name + " is eating");
    }
    
    public void sleep() {
        System.out.println(name + " is sleeping");
    }
}

// Child class (Subclass)
public class Dog extends Animal {
    String breed;
    
    // Dog inherits eat() and sleep() automatically!
    
    // Add Dog-specific method
    public void bark() {
        System.out.println("Woof woof!");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.name = "Buddy";
        myDog.breed = "Golden Retriever";
        
        myDog.eat();    // Buddy is eating (inherited)
        myDog.sleep(); // Buddy is sleeping (inherited)
        myDog.bark();  // Woof woof! (Dog-specific)
    }
}

The super Keyword

Use super to call parent class methods and constructors:

public class Animal {
    String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public void makeSound() {
        System.out.println("Some sound");
    }
}

public class Cat extends Animal {
    public Cat(String name) {
        super(name);  // Call parent constructor
    }
    
    @Override  // Annotation - marks override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

Polymorphism

Polymorphism means "many forms". A single method can behave differently based on the object type.

Method Overriding

public class Shape {
    public void draw() {
        System.out.println("Drawing a shape");
    }
}

public class Circle extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
}

public class Square extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a square");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape shape1 = new Circle();
        Shape shape2 = new Square();
        
        shape1.draw();  // Drawing a circle
        shape2.draw();   // Drawing a square
    }
}

Using Polymorphism with Arrays

public class Main {
    public static void main(String[] args) {
        // Store different shapes in one array
        Shape[] shapes = new Shape[3];
        shapes[0] = new Circle();
        shapes[1] = new Square();
        shapes[2] = new Triangle();
        
        // Each draw() behaves differently!
        for (Shape shape : shapes) {
            shape.draw();
        }
    }
}

Abstract Classes

An abstract class is a class that cannot be instantiated. It's a blueprint for other classes.

Why Use Abstract Classes?

  • Provide common functionality to child classes
  • Force child classes to implement certain methods
  • Create a common interface

Creating Abstract Classes

// Abstract class - can't create instances of this
abstract class Animal {
    String name;
    
    // Abstract method - must be implemented by children
    public abstract void makeSound();
    
    // Regular method - inherited by children
    public void eat() {
        System.out.println(name + " is eating");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.name = "Buddy";
        myDog.eat();        // Buddy is eating
        myDog.makeSound();  // Woof!
        
        Animal myCat = new Cat();
        myCat.name = "Whiskers";
        myCat.makeSound();  // Meow!
    }
}

Interfaces

An interface is a contract that defines what methods a class must have. A class can implement multiple interfaces!

Creating Interfaces

// Interface - defines what to do, not how
interface Drawable {
    void draw();  // Abstract method - no body
}

interface Movable {
    void move();
}

// Class implements both interfaces
class Car implements Drawable, Movable {
    @Override
    public void draw() {
        System.out.println("Drawing a car");
    }
    
    @Override
    public void move() {
        System.out.println("Car is moving");
    }
}

Interface vs Abstract Class

Interface Abstract Class
Can implement multiple Can extend only one
Only abstract methods (Java 7) Can have regular methods
No constructor Can have constructor
All fields are constants Can have regular fields

Default Methods (Java 8+)

interface Drawable {
    void draw();
    
    // Default method - has a body!
    default void print() {
        System.out.println("Printing...");
    }
}

Packages and Imports

Packages organize your code into folders. Imports bring in code from other packages.

Creating Packages

// Save as: com/mycompany/util/StringHelper.java
package com.mycompany.util;

public class StringHelper {
    public static String reverse(String str) {
        return new StringBuilder(str).reverse().toString();
    }
}

Importing Packages

// Import a single class
import java.util.Scanner;

// Import all classes from a package
import java.util.*;

// Import static members
import static java.lang.System.out;

public class Main {
    public static void main(String[] args) {
        out.println("Hello!");  // Using static import
        
        Scanner scanner = new Scanner(System.in);
    }
}

Common Packages

Package Purpose
java.lang Basic classes (String, Math, System)
java.util Collections, utilities
java.io Input/Output
java.time Date and time
java.net Networking

Exception Handling Basics

Exceptions are errors that occur during program execution. Handling them prevents crashes!

The Try-Catch Block

public class ExceptionDemo {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};
        
        try {
            System.out.println(numbers[5]);  // This will cause an error!
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Error: Index doesn't exist!");
            System.out.println("Exception: " + e.getMessage());
        }
        
        System.out.println("Program continues...");
    }
}

Multiple Catch Blocks

try {
    int result = 10 / 0;  // ArithmeticException
    String s = null;
    s.length();  // NullPointerException
} catch (ArithmeticException e) {
    System.out.println("Math error: " + e.getMessage());
} catch (NullPointerException e) {
    System.out.println("Null reference: " + e.getMessage());
} catch (Exception e) {
    System.out.println("Any other error: " + e.getMessage());
}

The Finally Block

try {
    System.out.println("Trying something...");
} catch (Exception e) {
    System.out.println("Error: " + e.getMessage());
} finally {
    System.out.println("This ALWAYS runs!");
}

Throwing Exceptions

public static void divide(int a, int b) throws ArithmeticException {
    if (b == 0) {
        throw new ArithmeticException("Cannot divide by zero!");
    }
    System.out.println(a / b);
}

Practice Exercises

Exercise 1: Create a Class

Create a Rectangle class with length and width. Add a method to calculate area.

public class Rectangle {
    private double length;
    private double width;
    
    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }
    
    public double getArea() {
        return length * width;
    }
    
    public static void main(String[] args) {
        Rectangle rect = new Rectangle(5, 3);
        System.out.println("Area: " + rect.getArea());  // 15
    }
}

Exercise 2: Inheritance

Create an Employee class and a Manager subclass.

class Employee {
    String name;
    double salary;
    
    public void work() {
        System.out.println(name + " is working");
    }
}

class Manager extends Employee {
    int teamSize;
    
    public void lead() {
        System.out.println(name + " is leading " + teamSize + " people");
    }
}

public class Exercise2 {
    public static void main(String[] args) {
        Manager mgr = new Manager();
        mgr.name = "Alice";
        mgr.salary = 80000;
        mgr.teamSize = 5;
        
        mgr.work();  // From Employee
        mgr.lead();  // Manager-specific
    }
}

Exercise 3: Interface

Create an interface Playable and implement it in a Game class.

interface Playable {
    void play();
}

class Game implements Playable {
    private String name;
    
    public Game(String name) {
        this.name = name;
    }
    
    @Override
    public void play() {
        System.out.println("Playing " + name + "!");
    }
}

public class Exercise3 {
    public static void main(String[] args) {
        Game game = new Game("Minecraft");
        game.play();  // Playing Minecraft!
    }
}

Exercise 4: Exception Handling

Handle division by zero.

public class Exercise4 {
    public static int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("Cannot divide by zero!");
        }
        return a / b;
    }
    
    public static void main(String[] args) {
        try {
            System.out.println(divide(10, 0));
        } catch (ArithmeticException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}

Exercise 5: Polymorphism

Create shapes with overridden methods.

abstract class Shape {
    abstract double getArea();
}

class Circle extends Shape {
    double radius;
    
    Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    double getArea() {
        return Math.PI * radius * radius;
    }
}

class Rectangle extends Shape {
    double width, height;
    
    Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    double getArea() {
        return width * height;
    }
}

public class Exercise5 {
    public static void main(String[] args) {
        Shape[] shapes = {new Circle(5), new Rectangle(4, 6)};
        
        for (Shape s : shapes) {
            System.out.println("Area: " + s.getArea());
        }
    }
}

Summary

In this guide, you learned:

  • ✅ What OOP is and the four pillars
  • ✅ How to create classes and objects
  • ✅ How to use constructors
  • ✅ What encapsulation is and why it matters
  • ✅ How inheritance works
  • ✅ What polymorphism is
  • ✅ How to create abstract classes
  • ✅ How to use interfaces
  • ✅ How to organize code with packages
  • ✅ How to handle exceptions

Next Steps: Move on to Java Advanced Guide to learn about collections, streams, lambdas, and more!


You're becoming a Java pro! Keep going! 💪

Clone this wiki locally