Abstraction
Abstraction means hiding complex implementation details and exposing only what's necessary to use
something. When you call List.add(), you don't need to know how the list resizes its internal array —
you just need to know it adds an element. In Java, abstraction is achieved mainly through abstract
classes and interfaces.
Abstract Classes
An abstract class is declared with the abstract keyword. It can contain a mix of:
| Member | Description |
|---|---|
| Abstract methods | Declared with no body — every concrete subclass must provide an implementation |
| Regular methods | Have a full implementation, shared by all subclasses just like normal inheritance |
new. Trying new Shape() on an abstract Shape class is a compile error — abstract classes exist to be extended, not instantiated.Worked Example: Shape, Circle, Rectangle
Imagine an abstract Shape class that declares an abstract area() method. Every shape has an
area, but how it's calculated is completely different for a circle versus a rectangle — that calculation
belongs to each specific subclass.
Example: Abstract Shape with Two Implementations
abstract class Shape {
public abstract double area();
public void describe() {
System.out.println("This shape's area is " + this.area());
}
}
class Circle extends Shape {
private double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width, height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
}
What's happening:
Shapedeclaresarea()asabstract— it has no body, only a signature.describe()is a regular method with a real implementation, shared by every subclass without being rewritten.CircleandRectangleeach provide their ownarea()— the calculation is completely different, but callers using aShapereference don't need to know or care which one they have.
Using the Abstract Type
Shape c = new Circle(5);
Shape r = new Rectangle(4, 6);
c.describe(); // This shape's area is 78.53...
r.describe(); // This shape's area is 24.0
Each call to describe() internally calls area(), and Java resolves that call to whichever
subclass's implementation actually applies — the same runtime polymorphism you saw with method overriding.
Abstraction vs. Encapsulation
These two concepts are closely related but not the same thing. Encapsulation is about hiding an object's data (fields) behind getters and setters. Abstraction is about hiding complexity — the "how" of a task — behind a simple interface, regardless of whether any data is involved. A well-designed class typically uses both together.