extends establishes single inheritance: a subclass automatically has every non-private field and method of its superclass, plus whatever it adds or overrides itself. Polymorphism is the resulting behavior at a method call site: when a subclass overrides a method, calling that method through a superclass-typed reference still invokes the subclass's version, because Java resolves overridden methods based on the object's actual runtime type — dynamic dispatch — not the declared type of the variable holding the reference.
extends: single inheritance
Dog automatically has eat() without redeclaring it, and provides its own version of makeSound() — super() explicitly calls the parent constructor, required as the first statement whenever the parent has no no-argument constructor.
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() { System.out.println(name + " is eating"); }
public void makeSound() { System.out.println("..."); }
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // must call the parent's constructor explicitly
}
@Override
public void makeSound() { // overrides the parent's version
System.out.println(name + " says Woof!");
}
}Polymorphism: resolved by the ACTUAL object, not the reference type
Even though pet is declared as Animal, calling makeSound() runs Dog's version — the JVM looks at what pet actually points to at runtime, ignoring the declared reference type entirely for this decision.
Animal pet = new Dog("Rex"); // declared type: Animal, actual type: Dog
pet.makeSound(); // prints "Rex says Woof!" — Dog's override runs
Animal[] animals = { new Dog("Rex"), new Cat("Whiskers") };
for (Animal a : animals) {
a.makeSound(); // each one calls ITS OWN override, through the same Animal-typed variable
}super: accessing the parent's version explicitly
super.makeSound() inside the override calls the parent's original implementation, letting a subclass extend rather than completely replace inherited behavior.
public class Puppy extends Dog {
@Override
public void makeSound() {
super.makeSound(); // calls Dog's makeSound() first
System.out.println("(but it's more of a yip)");
}
}