The <code>@Override</code> Annotation in Java

@Override tells the compiler "this method is meant to override a method from a supertype". If it doesn't actually override anything β€” a typo in the name, a wrong parameter type, a changed parent API β€” the compiler rejects the code. That's the whole value of the annotation.

The bug it prevents

public class Point {
    private final int x, y;
    public Point(int x, int y) { this.x = x; this.y = y; }

    public boolean equals(Point other) {          // ❌ NOT an override β€” overload!
        return x == other.x && y == other.y;
    }
}

var a = new Point(1, 1);
var b = new Point(1, 1);
Set<Object> set = new HashSet<>();
set.add(a);
set.contains(b);                                   // false β€” HashSet calls equals(Object)

With @Override, the compiler catches this immediately:

@Override
public boolean equals(Point other) { ... }        // ❌ "method does not override"

@Override
public boolean equals(Object other) { ... }        // βœ… compiles

Where it applies

  • Overriding a parent class's method.
  • Implementing an interface method.
  • Overriding a default method from an interface.

Interface implementations

Since Java 6, @Override is valid on interface-method implementations. Always annotate β€” it protects you when the interface evolves.

What it can't catch

  • Logic bugs β€” the annotation only checks the signature.
  • Breaking the equals/hashCode contract β€” equals can be overridden correctly but implemented badly.

Common mistakes

  • Omitting @Override β€” the typo-override bug silently ships. Make it mandatory in your style guide and/or compiler settings (-Xlint:all, -Werror).
  • Putting @Override on a method that doesn't exist in the parent β€” the compiler catches it, but it signals either a misunderstanding or a refactor you missed.

Related

Pillar: Java annotations. See also polymorphism, equals & hashCode.