Why does Java not support multiple inheritance of classes, and what problem does that decision solve?
Because inheriting from two classes means inheriting two sets of state, and when the two sets overlap the language has no good answer. Imagine a class extending both A and B, where each declares a field called Reading size. The subclass inherits two distinct fields, occupying two separate places in the object layout.size is ambiguous, and assigning to one of them leaves the other untouched — so the object holds two different answers to the same question with no way for a caller to tell which one they got.
That is not a hypothetical. Languages that allow multiple inheritance of classes — C++, Python, Ruby — all had to add explicit qualification syntax so you can say which superclass's member you mean, and they all have rules about what happens when the diamond is implicit. The complexity is real and it lands in the code, not just in the language definition.
Java's answer is to split the two concerns. State — fields, constructors — comes from a single superclass, so there is never ambiguity about storage. Behaviour — method contracts — comes from any number of interfaces, and because an interface carried no fields historically, two interfaces declaring the same method were harmless: one implementation satisfied both.
public class Main {
public static void main(String[] args) {
// One superclass, several interfaces: no conflict.
Dog dog = new Dog();
System.out.println("dog name : " + dog.name());
System.out.println("dog pets : " + dog.pets());
System.out.println("dog trains: " + dog.train());
}
}
class Animal {
public String name() {
return "animal";
}
}
interface Pet {
default String pets() {
return "being a good pet";
}
}
interface Trainable {
default String train() {
return "learning tricks";
}
}
class Dog extends Animal implements Pet, Trainable {
@Override
public String pets() {
return "being a good dog";
}
}The output shows the practical result: a Dog is an Animal by inheritance, a Pet and a Trainable by interface, and there is no conflict anywhere. When you genuinely need behaviour from two unrelated hierarchies, Java's idiom is composition: hold the other object as a field and delegate to it.