Before the questions, make sure you can: distinguish an is-a relationship from a
has-a relationship and choose inheritance or composition accordingly; write a subclass
with extends and say exactly which members it inherits; explain what super() does, when
the compiler inserts it, and what happens if the superclass has no no-argument constructor; give
the order in which fields, initialiser blocks and constructors run; distinguish overriding from
overloading and state the rules an overriding method must obey; and say what final does to a
field, a method and a class.
Is-a versus has-a
- Inheritance (is-a). A
SavingsAccountis aBankAccount. Writeclass SavingsAccount extends BankAccount. - Composition (has-a, strong ownership). A
Carhas anEngine, and the engine has no independent life: theCarcreates it and it disappears with the car. - Aggregation (has-a, weak ownership). A
CoursehasStudentobjects, but the students exist before and after the course; the course merely holds references to them.
Prefer composition when in doubt: if you cannot say “every X is a Y” out loud without wincing,
do not use extends.
Writing a subclass
public class Vehicle {
protected String brand; // visible to subclasses
private int serial; // NOT accessible in the subclass
public Vehicle(String brand) { this.brand = brand; }
public void describe() { System.out.println("Vehicle: " + brand); }
}
public class Car extends Vehicle {
private int doors;
public Car(String brand, int doors) {
super(brand); // must be the FIRST statement
this.doors = doors;
}
@Override
public void describe() { // overriding
super.describe(); // optional call to the inherited version
System.out.println("with " + doors + " doors");
}
}
A subclass inherits all public and protected members (and package-private ones in the
same package). It does not inherit constructors, and it cannot directly touch
private fields of the superclass — it must go through inherited accessors and mutators.
private |
the declaring class only |
|---|---|
| (none) | any class in the same package |
protected |
same package, plus subclasses anywhere |
public |
everywhere |
Java supports single inheritance of classes: one extends only. Every class that
does not name a superclass extends Object, which is why every object has toString,
equals and hashCode.
Constructors, super(), and initialisation order
- A constructor begins with
this(...)orsuper(...). If you write neither, the compiler insertssuper()— the no-argument superclass constructor. - Therefore, if the superclass declares only constructors that take arguments, every
subclass constructor must call
super(...)explicitly. If it does not, the class does not compile. - Order of execution when
new Child()runs: the superclass constructor chain finishes first (up toObject), then the subclass's field initialisers and instance initialiser blocks in the order they appear in the source, then the body of the subclass constructor.
class A { A() { System.out.print("1"); } }
class B extends A {
int x = print("2");
{ System.out.print("3"); } // instance initialiser block
B() { System.out.print("4"); }
static int print(String s) { System.out.print(s); return 0; }
}
// new B() prints 1234
Overriding versus overloading
| Overloading | Overriding | |
|---|---|---|
| Where | same class (or inherited) | subclass redefines a superclass method |
| Signature | must differ | must be identical (name and parameter list) |
| Return type | irrelevant | same, or a subtype (covariant) |
| Access | free | may not be more restrictive than the original |
| Bound | at compile time (static binding) | at run time (dynamic binding) |
An overriding method may not throw broader checked exceptions, and static, final and
private methods cannot be overridden — a static method redeclared in a subclass is
hidden, not overridden. The @Override annotation is optional but valuable: it turns a
silent mistake (a misspelled name, a wrong parameter type, which would quietly become an
overload) into a compile-time error.
final
final on a variable means assign once; on a method, it cannot be overridden; on a class, it
cannot be extended (String is final). A final instance field must be definitely
assigned by the end of every constructor — it may be given its value in the declaration or in
the constructor, but not both, and never afterwards.
Composition in code
public class Car { // composition: the Car owns its Engine
private final Engine engine = new Engine(1600);
public void start() { engine.ignite(); } // delegation
}
public class Course { // aggregation: students exist independently
private ArrayList<Student> enrolled = new ArrayList<>();
public void enrol(Student s) { enrolled.add(s); }
}
Composition reuses code by delegating to a contained object rather than inheriting from a superclass; it is more flexible, because the contained object can be replaced at run time.
extendsmeans is-a; a field means has-a.- Constructors are not inherited;
super(...)must come first. - No no-argument superclass constructor ⇒ the subclass must call
super(...)explicitly. - Superclass constructor runs before the subclass body.
- Same signature = overriding; different signature = overloading.
privatemembers are not accessible in a subclass.
- Using
extendsfor a has-a relationship (class Car extends Engine). - Forgetting
super(...)when the superclass has no no-argument constructor. - Believing that redeclaring a field in a subclass overrides it — fields are hidden, not overridden.
- Changing the parameter list while “overriding” and creating an accidental overload.
Ready? Close the notes and practise.
37 questions. Predict the output before you check — that is the skill the exam measures.