Abstract class — partial implementation, single inheritance. Interface — pure contract, multiple inheritance.
Analogy: An abstract class is a partially-built house — some rooms are done (concrete methods), some are blueprints (abstract methods). An interface is a building code — it lists what capabilities a house MUST have, but doesn't build anything.
Abstract class:
abstract keyword.1abstract class Vehicle {2 protected String brand;3 protected int year;45 // Constructor6 public Vehicle(String brand, int year) {7 this.brand = brand;8 this.year = year;9 }1011 // Concrete method — shared behavior12 public void start() {13 System.out.println(brand + " starting...");14 }1516 // Abstract method — subclasses must implement17 public abstract double calculateFuelEfficiency();1819 // Static method20 public static boolean isNewerThan(Vehicle a, Vehicle b) {21 return a.year > b.year;22 }23}2425class Car extends Vehicle {26 private double mpg;2728 public Car(String brand, int year, double mpg) {29 super(brand, year);30 this.mpg = mpg;31 }3233 @Override34 public double calculateFuelEfficiency() {35 return mpg;36 }37}3839Vehicle v = new Car("Toyota", 2023, 32.5);40v.start(); // Toyota starting...41System.out.println(v.calculateFuelEfficiency()); // 32.5
Interface:
interface keyword.public abstract by default.public static final (constants) by default.default and static methods allowed.1interface Drawable {2 void draw(); // public abstract by default3}45interface Resizable {6 void resize(double factor);78 // Default method (Java 8+)9 default void doubleSize() {10 resize(2.0);11 }12}1314// Multiple interface implementation15class Circle implements Drawable, Resizable {16 private double radius;1718 public Circle(double radius) {19 this.radius = radius;20 }2122 @Override23 public void draw() {24 System.out.println("Drawing circle with radius " + radius);25 }2627 @Override28 public void resize(double factor) {29 radius *= factor;30 }31}3233Circle c = new Circle(5);34c.draw(); // Drawing circle with radius 535c.doubleSize(); // Uses default method — radius becomes 1036c.draw(); // Drawing circle with radius 10
Key differences:
When to use which: