Java Tutorial Series: This lesson is part of our comprehensive Complete Java Tutorial: Learn Java from Beginner to Advanced.
Inheritance in Java: extends, Parent-Child Relationships and Best Practices
Inheritance allows one class to derive from another class. A subclass can reuse accessible behavior and define additional behavior, while an overridden method can provide specialized implementation. Inheritance is powerful, but it should model a genuine is-a relationship; otherwise composition or interfaces often produce a more flexible design.
What Is Inheritance?
A subclass extends a superclass using extends. The subclass inherits accessible members according to Java's access rules, but constructors are not inherited.
Superclass and Subclass
The superclass provides general behavior and state, while the subclass specializes it. A good hierarchy moves genuinely common behavior upward without forcing unrelated classes into the same family.
The extends Keyword
A class can directly extend one superclass. Java does not support multiple class inheritance, which avoids ambiguity around inherited implementation.
A class can still implement multiple interfaces.
Inherited Members
public and protected members can be available to subclasses according to access rules. private superclass state remains encapsulated and is accessed through superclass methods when appropriate.
Package-private behavior also depends on package boundaries.
super Keyword
super refers to the superclass portion of the current object. It can call a superclass constructor or access an accessible superclass member.
It is useful when subclass behavior extends rather than completely replaces parent behavior.
Method Overriding
A subclass can provide a new implementation for an inherited instance method. The method signature must satisfy Java's overriding rules.
Use @Override to let the compiler verify your intention.
Protected Access
protected can allow subclass access, but broad protected state can create tight coupling. Prefer protected methods or stronger encapsulation when possible.
Upcasting
A subclass object can be assigned to a superclass reference. This supports polymorphism because callers can depend on the general type while receiving specialized behavior.
Downcasting
A superclass reference can sometimes be cast to a subclass type when the runtime object actually has that type. Unsafe casts throw ClassCastException.
Prefer polymorphic APIs that avoid frequent downcasting.
Inheritance and Design
Inheritance should represent a stable conceptual relationship. If a subclass needs to disable or contradict much of the superclass behavior, the hierarchy may be a poor fit.
Common Mistakes
Deep hierarchies, excessive protected state and inheritance used only for code reuse can make systems brittle.
Composition often gives more control over changing behavior.
Best Practices
Keep hierarchies shallow, favor meaningful abstractions, use @Override and prefer composition when the relationship is has-a rather than is-a.
Practical Examples
Simple Inheritance
A specialized type extends a general type.
class Vehicle { void start() { System.out.println("start"); } }
class Car extends Vehicle { void drive() { System.out.println("drive"); } }
Polymorphic Reference
A subclass object can be referenced through the superclass type.
Vehicle vehicle = new Car();
vehicle.start();
Common Mistakes and Troubleshooting
Most mistakes with object-oriented Java come from confusing a class with an object, misunderstanding which method or constructor is selected, exposing state unnecessarily, or assuming inheritance automatically makes a design better. Debug these problems by checking the declared type, runtime object, constructor path, access level and method-selection rules separately.
- Test normal, null, boundary and invalid inputs where they apply.
- Keep responsibilities small so object behavior is easier to understand.
- Prefer clear contracts over clever inheritance hierarchies.
- Use @Override when overriding a superclass or interface method.
- Do not expose mutable internal state without a deliberate reason.
Performance and Design Considerations
Object-oriented design is mainly about modeling behavior and responsibilities, not simply creating many classes. A good design keeps related state and behavior together, reduces unnecessary coupling and makes changes local. In larger Java applications, these choices affect testing, maintenance, dependency management and API stability.
Inheritance, interfaces and composition all have valid uses. The right choice depends on the relationship between the types, the expected variation and how much implementation sharing is actually required. When a topic is performance-sensitive, measure representative workloads rather than assuming that one object-oriented technique is automatically faster.
Practice Exercises
- Create a small example using the main concept in this article.
- Add at least one invalid or edge-case input and decide how the program should behave.
- Compare the concept with one related Java feature and explain the difference.
- Refactor one large class or method into smaller responsibilities.
- Write tests for the most important behavior.
- Explain the design choice as if you were answering an interview question.
Frequently Asked Questions
Is this topic important for Java interviews?
Yes. Core OOP concepts are frequently tested through definitions, code tracing, design questions and practical scenarios.
Should I memorize the syntax?
Learn the syntax through small programs, but focus more on the rule the syntax expresses and when the feature should be used.
Can I use this feature everywhere?
No. Each feature has trade-offs. Prefer the simplest design that clearly represents the requirement.
What should I learn next?
Connect this concept with the surrounding OOP topics, then apply it in a small Java project and test the behavior.
Quick Reference
| Concept | Core idea | Typical use |
|---|---|---|
| extends | Creates class inheritance | Specialization |
| super | Accesses superclass context | Constructor/member reuse |
| Override | Specialized implementation | Runtime polymorphism |
| Upcast | Subclass to parent reference | General APIs |
Conclusion
The goal of learning this Java OOP concept is not only to recognize its syntax. You should be able to explain how it behaves, identify its boundaries, compare it with related features and use it in a maintainable program. Practice the examples, test edge cases and apply the concept inside a realistic project.
Learn More
- Continue with the next Java OOP topic and compare the two concepts directly.
- Practice the examples with different inputs and object relationships.
- Review classes, objects, collections, exceptions and generics as your programs become larger.
Continue Learning Java
A practical Java path moves from classes and objects into constructors, inheritance, polymorphism, encapsulation, abstraction, interfaces and advanced object-oriented design. Keep each concept connected to a complete program rather than learning isolated definitions.
Deeper Learning Notes
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.
For practical Java development, connect this concept to the application's actual responsibilities and object relationships. Identify what state is owned by the class, which behavior belongs with that state, what callers should be allowed to know, and what implementation details should remain hidden. Compare the feature with at least one alternative, test normal and edge cases, and explain the trade-off. This approach produces code that is easier to review, test and maintain and also prepares you to explain the design clearly in interviews.