☕ Java Programming Guide

Master Object-Oriented Programming

Introduction to Java Programming

Java is a powerful, object-oriented programming language that emphasizes code reusability, security, and platform independence. This guide covers all fundamental OOP concepts and Java essentials.

1. Basic Structure of a Java Program

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
Note: The filename must match the public class name. This file would be saved as HelloWorld.java.

2. Object-Oriented Programming Principles

Java is built on four fundamental OOP principles:

🔹 Encapsulation

Bundling data (fields) and methods that operate on that data within a single unit (class), and restricting direct access to some components.

🔹 Inheritance

Creating new classes based on existing classes, inheriting their properties and methods while adding new functionality.

🔹 Polymorphism

The ability of objects to take on multiple forms. Same method name can behave differently based on the object calling it.

🔹 Abstraction

Hiding complex implementation details and showing only essential features to the user.

3. Variables and Data Types

Primitive Data Types

Type Size Default Value Example
byte 1 byte 0 byte age = 25;
short 2 bytes 0 short year = 2025;
int 4 bytes 0 int count = 100;
long 8 bytes 0L long distance = 1000000L;
float 4 bytes 0.0f float pi = 3.14f;
double 8 bytes 0.0d double price = 99.99;
char 2 bytes '\u0000' char grade = 'A';
boolean 1 bit false boolean isValid = true;

Reference Types

String name = "Alice";
int[] numbers = {1, 2, 3, 4, 5};
ArrayList<String> list = new ArrayList<>();

4. Classes and Objects

A class is a blueprint for creating objects. An object is an instance of a class.

Defining a Class

public class Person {
    // Instance variables (fields)
    private String name;
    private int age;
    
    // Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // Getter methods
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    // Setter methods
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        }
    }
    
    // Method
    public void introduce() {
        System.out.println("Hi, I'm " + name + " and I'm " + age + " years old.");
    }
}

Creating Objects

public class Main {
    public static void main(String[] args) {
        Person person1 = new Person("Alice", 25);
        person1.introduce();  // Output: Hi, I'm Alice and I'm 25 years old.
        
        person1.setAge(26);
        System.out.println(person1.getAge());  // Output: 26
    }
}
Tip: Use private fields with public getter/setter methods (encapsulation) to control access to class data.

5. Constructors

Constructors initialize objects when they are created.

Types of Constructors

public class Student {
    private String name;
    private int id;
    
    // Default constructor
    public Student() {
        this.name = "Unknown";
        this.id = 0;
    }
    
    // Parameterized constructor
    public Student(String name, int id) {
        this.name = name;
        this.id = id;
    }
    
    // Constructor overloading
    public Student(String name) {
        this.name = name;
        this.id = 0;
    }
}

6. Inheritance

Inheritance allows a class to inherit properties and methods from another class.

// Parent class (superclass)
public class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    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 {
    private String breed;
    
    public Dog(String name, String breed) {
        super(name);  // Call parent constructor
        this.breed = breed;
    }
    
    public void bark() {
        System.out.println(name + " is barking!");
    }
    
    // Method overriding
    @Override
    public void eat() {
        System.out.println(name + " the dog is eating dog food.");
    }
}

// Usage
Dog myDog = new Dog("Buddy", "Golden Retriever");
myDog.eat();    // Output: Buddy the dog is eating dog food.
myDog.bark();   // Output: Buddy is barking!
myDog.sleep();  // Output: Buddy is sleeping.
Important: Java supports single inheritance only (a class can extend only one class), but can implement multiple interfaces.

7. Polymorphism

Method Overloading (Compile-time Polymorphism)

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    
    public double add(double a, double b) {
        return a + b;
    }
    
    public int add(int a, int b, int c) {
        return a + b + c;
    }
}

Method Overriding (Runtime Polymorphism)

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 Rectangle extends Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle");
    }
}

// Polymorphic behavior
Shape shape1 = new Circle();
Shape shape2 = new Rectangle();

shape1.draw();  // Output: Drawing a circle
shape2.draw();  // Output: Drawing a rectangle

8. Abstract Classes

Abstract classes cannot be instantiated and may contain abstract methods (methods without implementation).

public abstract class Vehicle {
    protected String brand;
    
    public Vehicle(String brand) {
        this.brand = brand;
    }
    
    // Abstract method (no implementation)
    public abstract void start();
    
    // Concrete method
    public void stop() {
        System.out.println(brand + " is stopping.");
    }
}

public class Car extends Vehicle {
    public Car(String brand) {
        super(brand);
    }
    
    @Override
    public void start() {
        System.out.println(brand + " car is starting with ignition.");
    }
}

// Usage
Vehicle myCar = new Car("Toyota");
myCar.start();  // Output: Toyota car is starting with ignition.
myCar.stop();   // Output: Toyota is stopping.

9. Interfaces

Interfaces define a contract that classes must follow. All methods are implicitly abstract and public.

public interface Drawable {
    void draw();  // implicitly public and abstract
    void resize(int width, int height);
}

public interface Colorable {
    void setColor(String color);
}

// A class can implement multiple interfaces
public class Circle implements Drawable, Colorable {
    private int radius;
    private String color;
    
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
    
    @Override
    public void resize(int width, int height) {
        this.radius = width / 2;
    }
    
    @Override
    public void setColor(String color) {
        this.color = color;
    }
}
Note: Since Java 8, interfaces can have default methods and static methods with implementation.

10. Exception Handling

Exception handling allows you to manage runtime errors gracefully.

Try-Catch Block

public class ExceptionExample {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;  // ArithmeticException
        } catch (ArithmeticException e) {
            System.out.println("Error: Cannot divide by zero");
            System.out.println("Message: " + e.getMessage());
        } finally {
            System.out.println("This always executes");
        }
    }
}

Multiple Catch Blocks

try {
    int[] arr = new int[5];
    arr[10] = 50;  // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("Array index out of bounds");
} catch (Exception e) {
    System.out.println("General exception occurred");
}

Throwing Exceptions

public void checkAge(int age) throws IllegalArgumentException {
    if (age < 18) {
        throw new IllegalArgumentException("Age must be 18 or older");
    }
    System.out.println("Age is valid");
}

11. Collections Framework

Java provides powerful data structures through the Collections Framework.

ArrayList

import java.util.ArrayList;

ArrayList<String> fruits = new ArrayList<>();

// Adding elements
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");

// Accessing elements
System.out.println(fruits.get(0));  // Apple

// Iterating
for (String fruit : fruits) {
    System.out.println(fruit);
}

// Removing elements
fruits.remove("Banana");
fruits.remove(0);  // Remove by index

HashMap

import java.util.HashMap;

HashMap<String, Integer> ages = new HashMap<>();

// Adding key-value pairs
ages.put("Alice", 25);
ages.put("Bob", 30);
ages.put("Charlie", 35);

// Accessing values
System.out.println(ages.get("Alice"));  // 25

// Iterating
for (String name : ages.keySet()) {
    System.out.println(name + ": " + ages.get(name));
}

// Check if key exists
if (ages.containsKey("Bob")) {
    System.out.println("Bob's age: " + ages.get("Bob"));
}

HashSet

import java.util.HashSet;

HashSet<String> uniqueNames = new HashSet<>();

uniqueNames.add("Alice");
uniqueNames.add("Bob");
uniqueNames.add("Alice");  // Duplicate, won't be added

System.out.println(uniqueNames.size());  // 2 (duplicates removed)

12. Generics

Generics enable types (classes and interfaces) to be parameters when defining classes, interfaces, and methods.

public class Box<T> {
    private T item;
    
    public void setItem(T item) {
        this.item = item;
    }
    
    public T getItem() {
        return item;
    }
}

// Usage
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
String value = stringBox.getItem();

Box<Integer> intBox = new Box<>();
intBox.setItem(123);
int number = intBox.getItem();

13. File I/O

Writing to a File

import java.io.FileWriter;
import java.io.IOException;

try {
    FileWriter writer = new FileWriter("output.txt");
    writer.write("Hello, World!\n");
    writer.write("This is Java file I/O.\n");
    writer.close();
    System.out.println("Successfully wrote to file");
} catch (IOException e) {
    System.out.println("An error occurred");
    e.printStackTrace();
}

Reading from a File

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

try {
    File file = new File("input.txt");
    Scanner reader = new Scanner(file);
    
    while (reader.hasNextLine()) {
        String line = reader.nextLine();
        System.out.println(line);
    }
    reader.close();
} catch (FileNotFoundException e) {
    System.out.println("File not found");
    e.printStackTrace();
}

14. Static vs Instance Members

public class Counter {
    // Static variable (shared by all instances)
    private static int totalCount = 0;
    
    // Instance variable (unique to each instance)
    private int instanceCount = 0;
    
    public Counter() {
        totalCount++;
        instanceCount++;
    }
    
    // Static method (can be called without creating an object)
    public static int getTotalCount() {
        return totalCount;
    }
    
    // Instance method
    public int getInstanceCount() {
        return instanceCount;
    }
}

// Usage
Counter c1 = new Counter();
Counter c2 = new Counter();

System.out.println(Counter.getTotalCount());  // 2 (static)
System.out.println(c1.getInstanceCount());    // 1 (instance)

Key Takeaways