HOWTO · Java
How to Extend Two Classes in Java
Learn why a Java class can extend only one class, and how interfaces and composition combine behavior from multiple types.
On this page
A Java class cannot extend two classes. A class has one direct superclass, so a declaration such as class Child extends First, Second is not valid Java. To combine behavior from multiple types, extend one class and implement any number of interfaces, or hold other objects and delegate work to them with composition.
Why a Java Class Cannot Extend Two Classes
Java uses single inheritance for classes: each class can name at most one superclass with extends. This gives an object one class inheritance chain and avoids ambiguity about which superclass implementation or state should apply when two parents define the same member. The compiler rejects a class declaration that lists two superclasses; this is a compile-time restriction, not a failure that happens while the program runs.
The following is deliberately invalid Java syntax and will not compile: class Child extends First, Second {}. Use one superclass when the new class is genuinely a specialized kind of that type. The next section shows how interface contracts can describe additional capabilities.
Use One Superclass and Implement Multiple Interfaces
A class can extend one class and implement multiple interfaces. The superclass can provide shared state or implementation, while each interface declares a capability the class promises to provide. The Java keywords matter: a class uses extends for its superclass and implements for interfaces. An interface may itself extend multiple interfaces, but that does not give a class multiple class superclasses.
This complete example defines two interface contracts and implements both alongside one superclass:
public class CatalogItem extends Record implements Printable, Identifiable {
CatalogItem(String name) {
super(name);
}
@Override
public void printLabel() {
System.out.println(name());
}
@Override
public String id() {
return "item-" + name().toLowerCase();
}
public static void main(String[] args) {
CatalogItem item = new CatalogItem("Book");
item.printLabel();
System.out.println(item.id());
}
}
interface Printable {
void printLabel();
}
interface Identifiable {
String id();
}
class Record {
private final String name;
Record(String name) {
this.name = name;
}
String name() {
return name;
}
}
Book
item-book
CatalogItem inherits the name() implementation from Record and supplies the methods required by both interfaces. Interfaces are useful when unrelated classes should share a type or capability contract. They do not automatically provide state or class implementation as a second superclass would.
Combine Behavior from Classes with Composition
Composition combines objects through a has-a relationship: a class stores references to collaborators and calls their methods. This is useful when the behaviors come from independently useful classes, or when the collaborator should be replaceable. The containing class controls which operations it exposes and can delegate only the work its callers need.
Here a SmartDevice contains a PowerController and a MessageSender, then delegates operations to them:
public class SmartDevice {
private final PowerController power = new PowerController();
private final MessageSender sender = new MessageSender();
void start() {
power.powerOn();
}
void sendMessage(String message) {
sender.send(message);
}
public static void main(String[] args) {
SmartDevice device = new SmartDevice();
device.start();
device.sendMessage("Ready");
}
}
class PowerController {
void powerOn() {
System.out.println("Power on");
}
}
class MessageSender {
void send(String message) {
System.out.println("Sending: " + message);
}
}
Power on
Sending: Ready
The SmartDevice does not become a PowerController or a MessageSender; it uses both. In a larger program, collaborators can be supplied through a constructor or represented by interfaces, which makes it easier to substitute implementations and test the containing class independently.
Choose the Right Reuse Pattern
Choose class inheritance when the new type truly is a specialized form of one superclass and should inherit its implementation. Add interfaces when a type needs to promise capabilities shared with other classes. Use composition when behavior should be assembled from parts, delegated, or changed independently.
Keep each class focused on a clear responsibility and expose only the operations callers need. Prefer small interface contracts over broad ones, and avoid duplicating behavior that belongs in a shared collaborator. These choices make relationships easier to understand, test, and adapt as requirements change. In short, Java does not allow a class to extend two classes; one superclass, multiple interface contracts, and composed collaborators cover the common reuse needs.