Excluding Object
, which has no superclass, every Java class has one and only one direct superclass. That superclass is implicitly Object
if no other superclass is specified using the reserved word extends
.
If class B
extends from class A
, then the subclass B
inherits the accessible members from the superclass A
. Constructors are not inherited but they can be invoked from the subclass constructor using super(…)
. In fact, a whole chain of constructors starting from the top superclass is invoked when you create an instance of a subclass (see the lesson Class Initialization and Inheritance for more details about this).
Inherited methods can be overridden as is explained below.
Overriding Methods
A superclass instance method (non-static method) is overridden when you write a new instance method in the subclass that has the same signature and return type (or subclass of that type).If the subclass method has the same signature (method name and parameter type and order) but a different return type then you’ll get a compiler error. There are, however, some changes that you can make in an overriding method:
- The access modifier can allow more access than the overridden method (but not less)
- You can make abstract any non-abstract overridden method (and so the subclass will also be abstract)
You can learn more about access modifiers and abstract classes in the lessons about these topics:
The following are examples of valid and invalid method overriding:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
class A { Object getSomething() { … } } // OK: covariant return type (String is a subclass of Object) class B extends A { String getSomething() { … } } // Error: modifier allows less access (private < default) class C extends A { private String getSomething() { … } } // Error: different return type class D extends A { int getSomething() { … } } // Error: if a method is abstract then the class must also be abstract class E extends A { abstract Object getSomething(); // no method body } // OK abstract class F extends A { abstract Object getSomething(); // no method body } |
Although it’s not shown in the previous example, it’s a good practice use the @Override
annotation to tell the compiler that you intend to override a method (and so there will be a compiler error if the method doesn’t exist in one of the super classes):
1 2 3 4 5 6 7 8 9 10 |
class MyAction extends AbstractAction { @Override public void actionPerformed(ActionEvent e) { // your code here } } |
Inheritance and Exceptions
The following table illustrates how inheritance affects to the exceptions declared in thethrows
clause of constructors and overriding methods:
Constructors |
|
---|---|
Overriding methods |
|
Below are examples of valid and invalid declarations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
class Exception1 extends Exception { } class Exception2 extends Exception1 { } class Exception3 extends Exception { } class A { A() throws Exception1, Exception2 { } void getSomething() throws Exception1, Exception2 { } } // OK: all the exceptions in the superclass constructor class B extends A { B() throws Exception1, Exception2 { } } // OK: Exception is a superclass of Exception1 and Exception2 class C extends A { C() throws Exception { } } // Error: Exception1 is missed (it would be OK if it threw only // Exception1 because it covers both: Exception1 and Exception2) class D extends A { D() throws Exception2 { } } // OK: Exception1 is a subset of [Exception1, Exception2] class E extends A { E() throws Exception { } void getSomething() throws Exception1 { } } // Error: Exception3 is not a subset of [Exception1, Exception2] class F extends A { void getSomething() throws Exception1, Exception3 { } } |
To learn more about exceptions you can read the following lessons: