Method Overloading: It allows multiple methods in the same class with the same name but different parameter lists (different type, number, or order). This is a compile-time polymorphism feature.

Example:

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

    double add(double a, double b) {
        return a + b;
    }
}

Method Overriding: It allows a subclass to provide a specific implementation of a method already defined in its superclass. The method must have the same name, return type, and parameters. This is a runtime polymorphism feature.

Example:

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.sound(); // Outputs: Dog barks
    }
}