1. Compile-time polymorphism (Method Overloading): This occurs when multiple methods in the same class have the same name but different parameters.
  2. Runtime polymorphism (Method Overriding): This occurs when a subclass provides a specific implementation of a method that is already defined in its parent class.

Example Code

// Compile-time polymorphism (Method Overloading)
class Adder {
    static int add(int a, int b) {
        return a + b;
    }
    static double add(double a, double b) {
        return a + b;
    }
}

public class TestPolymorphism {
    public static void main(String[] args) {
        System.out.println(Adder.add(10, 20)); // Output: 30
        System.out.println(Adder.add(10.5, 20.5)); // Output: 31.0
    }
}

// Runtime polymorphism (Method Overriding)
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 TestPolymorphism {
    public static void main(String[] args) {
        Animal myAnimal = new Dog();
        myAnimal.sound();  // Output: Dog barks
    }
}