Topic 5.6
Abstract Classes
In one line
An abstract class is a partly finished class: it can hold fields, constructors and working methods, plus abstract methods with no body that every concrete subclass must fill in. You can't create an object of an abstract class directly.
Think of it like this
A fill-in-the-blanks form. The bank's account-opening form already has the bank's name, the rules and the signature line printed. It leaves blanks for 'Name' and 'Address' that each customer must fill in. You can't open an account with the blank form itself; you need a filled-in copy. The printed parts are the concrete methods; the blanks are the abstract methods.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Abstract class
- A class marked
abstract. It can't be instantiated withnewand may contain abstract methods. - Abstract method
- A method declared with
abstractand no body, ending in a semicolon. Subclasses must supply the body. - Concrete class
- A normal, non-abstract class. You can create objects from it, and it has a body for every method.
- Instantiate
- Create an object of a class with
new. - Template Method
- A design pattern: a parent method fixes the order of steps and lets subclasses fill in some steps.
- Hook method
- A step in a template method that subclasses can override. It may be abstract (must fill in) or have a default body (may fill in).
Step by step
01Declaring an abstract class
Put abstract before class. Inside, declare abstract methods with abstract and a semicolon instead of a body. Concrete methods in the same class can call the abstract ones, because at run time this will always be some concrete subclass that has a body for them.
describe() below works for every shape without knowing any shape's formula: area() and perimeter() are dispatched dynamically to the real subclass (Topic 5.4).
abstract class Shape {
private final String name;
protected Shape(String name) { this.name = name; } // yes, abstract classes have constructors
abstract double area(); // no body: subclasses decide
abstract double perimeter();
String describe() { // concrete: uses the abstract methods
return name + ": area=" + area() + " perimeter=" + perimeter();
}
}02Why can't I call new Shape()?
If you could, new Shape("blob").area() would have no code to run. Rather than fail at run time, Java forbids it at compile time. At the bytecode level the class carries the ACC_ABSTRACT flag, and the JVM itself throws InstantiationError if anything (such as hand-written bytecode) tries new on it.
But abstract classes *do* have constructors. They run as part of building a subclass object, via super(...), exactly like Topic 5.1. Making the constructor protected documents that it exists only for subclasses.
03The subclass must finish the job
A concrete subclass must override every abstract method it inherits, from any ancestor. Miss one and the compiler names the first missing method.
An intermediate class can stay abstract: abstract class Car extends Vehicle might implement wheels() but leave fuel() open. Only the last, concrete classes (PetrolCar, ElectricCar) must have everything.
04Template Method: the parent controls the flow
An exporter always does the same steps: header, every row, footer. Only the *format* of each step changes between CSV and JSON. Put the fixed sequence in a final method in the abstract parent; declare the varying steps abstract (must override) or give them an empty default body (may override, called hooks).
Making the template method final stops subclasses from reordering or skipping steps. This is the Template Method pattern; the System Design course covers it in depth at /topic/phase-2/template-method. The JDK uses it widely: java.io.InputStream.read(byte[], int, int) is built on the abstract single-byte read(), and AbstractList builds iteration on your get and size.
05Abstract classes in the JDK
You use abstract classes every day: java.util.AbstractList, AbstractMap, java.io.InputStream, java.io.Reader, java.lang.Number (the parent of Integer, Double, BigDecimal, with abstract intValue(), doubleValue(), and so on).
Number shows the idea perfectly: every number can give you an int or a double, but each kind does it differently, and there is no such thing as a plain 'Number' object.
Try it yourself
- 1
Add a Triangle
In the Shape example, add
Triangle(double a, double b, double c). Use Heron's formula for the area:s = (a+b+c)/2, area =Math.sqrt(s*(s-a)*(s-b)*(s-c)). For 3, 4, 5, predictarea=6.00 perimeter=12.00, then run. - 2
Forget a method on purpose
Delete
perimeter()fromRectangleand compile. Read which method the compiler says is missing. Then mark Rectangleabstractinstead and see the error move tonew Rectangle(2, 3). - 3
Try to override the template
In the exporter example, add
public void export(List<String> rows) { }toTextExporter. The compiler stops you becauseexportisfinal. That protection is the point of the pattern.
Code & diagrams
Expected output
Shape constructor for circle
Shape constructor for rectangle
circle: area=3.14 perimeter=6.28
rectangle: area=6.00 perimeter=10.00Expected output
== CSV export ==
name,score
Asha,90
Ravi,85
(2 rows)
== TEXT export ==
Asha scored 90
Ravi scored 85
(2 rows)Expected output
PetrolCar: 4 wheels, runs on petrol
ElectricCar: 4 wheels, runs on electricity
Car abstract? true
PetrolCar abstract? falseBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Instantiate an abstract class
Write new Shape() where Shape is abstract.
abstract class Shape { abstract double area(); }
public class Main { public static void main(String[] a) { Shape s = new Shape(); } }Break #2
Leave an abstract method unimplemented
Extend Shape without overriding area().
abstract class Shape { abstract double area(); }
class Circle extends Shape { }Break #3
Combine abstract with final
Declare abstract final class Shape.
abstract final class Shape { }Myth vs fact
Myth
Abstract classes can't have constructors.
Fact
They can and often do. The constructor runs when a subclass object is created, through super(...).
Myth
An abstract class must have at least one abstract method.
Fact
It needn't. A class with no abstract methods can still be declared abstract just to prevent direct instantiation (for example, a base class only meant for extension).
Myth
Since Java 8 interfaces have default methods, abstract classes are obsolete.
Fact
Interfaces still can't hold instance state, constructors, or non-public instance methods other than private helpers. Abstract classes remain the right tool for shared state plus a template (Topic 5.9).
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Bytecode: an abstract class has
ACC_ABSTRACTin its access flags; abstract methods haveACC_ABSTRACTand noCodeattribute. A call to an abstract method is a normalinvokevirtual, dispatched through the vtable slot that the concrete subclass fills in. - ▸
If a class is compiled against an older version of an abstract parent and the parent later gains a new abstract method, calling it on the old subclass throws
AbstractMethodErrorat run time (no recompilation means no compile error). That's binary incompatibility, and it's exactly what default methods in interfaces were designed to avoid (Topic 5.8). - ▸
Effective Java's advice, 'design and document for inheritance or else prohibit it', applies doubly to abstract classes: document which hooks are called, in what order, and from which methods (
@implSpecin Javadoc). The JDK'sAbstractCollection.addAlldocuments that it callsaddfor each element, which is precisely what makes the composition example in Topic 5.12 behave the way it does.
Remember this
- 1
Mark a class
abstractwhen it represents a general idea that should never exist on its own. AShapeis always some particular shape; a plainnew Shape()makes no sense. The compiler then refusesnew Shape()withShape is abstract; cannot be instantiated. - 2
An abstract method has a signature and no body:
abstract double area();. It says 'every concrete shape can compute its area, but I can't say how'. A class with even one abstract method must itself be declared abstract. - 3
A concrete subclass (one that is not abstract) must override every inherited abstract method, or the compiler says
Circle is not abstract and does not override abstract method area() in Shape. A subclass may also stay abstract and leave some methods for its own children. - 4
Abstract classes are full classes in every other way: they have fields (state), constructors (called via
super(...)from subclasses), concrete methods, static members, and any access modifiers. That is the main difference from interfaces (Topic 5.9). - 5
The most common use is the Template Method pattern: a concrete (often
final) method defines the fixed steps of an algorithm and calls abstract 'hook' methods for the steps that vary. The parent controls the flow; the children supply the details. - 6
Illegal combinations:
abstract final(can't be both unfinishable and unextendable),abstract private(a private method can't be overridden, so could never get a body), andabstract static(static methods aren't overridden).
Explain it without notes
What's an abstract class and why can't you instantiate it?
Can an abstract class have a constructor? When does it run?
Explain the Template Method pattern and why the template method is usually final.
Which modifier combinations with abstract are illegal, and why?
Practice
Create an abstract Employee with name, an abstract double monthlyPay(), and a concrete payslip() returning "<name>: <pay>". Add SalariedEmployee (annual / 12) and HourlyEmployee (rate × hours).
Write an abstract Game with a final play() that calls start(), then takeTurn() three times, then end(). Implement Chess with its own messages.
Make an abstract Animal with an abstract sound() and a concrete speak() that prints "<class name> says <sound>". Create Dog and Cow and call speak() on both through an Animal[].
Trade-offs
- ↔
An abstract class can share state and code, but a subclass spends its single
extendson it. If a type might need another parent, start with an interface and offer an abstract class as an optional helper (the skeletal implementation idiom, Topic 5.9). - ↔
Template methods give the parent tight control of the flow, which also means subclasses depend on the exact call order. Changing the order later is a breaking change for every subclass.
Done when you can
Done when you can declare an abstract class with abstract and concrete methods and a constructor.
Done when you can explain why
newis forbidden and how the constructor still runs.Done when you can implement the Template Method pattern with a final template and hooks.
Done when you can name JDK abstract classes like
Number,InputStreamandAbstractList.Done when you know the illegal modifier combinations with
abstract.