Abstract class vs interface in Java
State and constructors vs multiple inheritance of type.
Half-built house vs job description
An abstract class is a half-built house you finish: it can have instance fields, constructors and methods of any access level — but a class can extend only one. An interface is a job description anyone can meet: no instance state, no constructors, but a class can implement many.
Constructors you can't call
You can't write new Vehicle(). So what does this print?
abstract class Vehicle {
Vehicle() { System.out.print("V"); }
}
class Bus extends Vehicle {
Bus() { System.out.print("B"); }
}
void main() {
new Bus();
System.out.println();
}VBBBVCompile error
Show the answer
Abstract classes do have constructors. Creating a Bus runs Vehicle's constructor first (the implicit super()), then Bus's. They exist so subclasses can set up the inherited state.
Side by side
Instance fields & constructors: abstract class only. Inheriting several at once: interfaces only. Methods with bodies: both. **Creating directly with new**: neither. And an interface can never declare a constructor — there's no instance state to initialize.
Sharing state
interface Account {
long BALANCE = 0; // static final!
}Interface fields are shared constants — no per-object balance, no constructor to validate it.
abstract class Account {
protected long balance;
Account(long opening) {
if (opening < 0)
throw new IllegalArgumentException();
balance = opening;
}
}Per-object state plus constructor validation, shared by Savings and Checking.
Unrelated types, one ability
Invoice, User and Product already extend different base classes. All three need toCsv(). Abstract class or interface?
Think about it, then reveal the answer
An interface like CsvExportable. They already have superclasses, so another class can't be added — but any class can implement an interface. Rule of thumb: "is-a family" → abstract class; "can-do" → interface.
The JDK uses both together
The JDK pairs them: the List interface is the contract, and the abstract class AbstractList is a skeleton that implements most of it. You program against List, and if you build your own list you extend AbstractList and write just get() and size().
Key takeaways
- Abstract class: fields + constructors, single inheritance
- Interface: no instance fields or constructors, multiple implementation
- Neither can be created with new; both can have methods with bodies
- 'is-a family' → abstract class; 'can-do' → interface
💡 An abstract class is a half-built house you finish; an interface is a job description anyone can meet.
An abstract class doesn't need any abstract methods: abstract class Base { } is perfectly legal. Sometimes abstract is there only to forbid new Base().
Practice questions
What does this print?
abstract class Animal {
Animal() { System.out.print("A"); }
abstract String sound();
}
class Dog extends Animal {
Dog() { System.out.print("D"); }
String sound() { return "!"; }
}
void main() {
System.out.println(new Dog().sound());
}- AD!
- D!
- DA!
- Compile error: abstract classes can't have constructors
Check your answer
AD!. Creating a Dog runs Animal's constructor first (implicit super()), then Dog's, then sound() is printed.
Savings and Checking accounts share a `balance` field, the same deposit() code, and a constructor that rejects negative opening balances. What should Account be?
- An abstract class
- An interface with default methods
- A marker interface
- An interface with a BALANCE constant
Check your answer
An abstract class. Shared per-object state (balance) and constructor validation need an abstract class; interfaces can't hold instance fields or constructors.