Java · Course navigation

Java abstract classes and enums

Define a shared base with an abstract method, and a fixed set of constants with fields.

On this page
Before you start

Java classes and inheritance.

  • Define a shared base with an abstract method, and a fixed set of constants with fields.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

An abstract class cannot be instantiated. It describes what its subclasses share and declares abstract methods that every concrete subclass must implement. Code written against the abstract type, such as a method that takes any Shape, works for all subclasses through polymorphism.

An enum is a class with a fixed set of instances. Each constant can have fields, a constructor, and methods, and values() returns all of them in order. Enums are safer than integer or string constants because the compiler rejects values that are not in the set, and they work with switch.

Code example

Java
import java.util.Locale;

class Main {
  static abstract class Shape {
    abstract double area();

    String describe() {
      return getClass().getSimpleName() + " area " + String.format(Locale.ROOT, "%.2f", area());
    }
  }

  static class Circle extends Shape {
    private final double radius;

    Circle(double radius) {
      this.radius = radius;
    }

    double area() {
      return Math.PI * radius * radius;
    }
  }

  static class Rect extends Shape {
    private final double width;
    private final double height;

    Rect(double width, double height) {
      this.width = width;
      this.height = height;
    }

    double area() {
      return width * height;
    }
  }

  enum Level {
    LOW(1), MEDIUM(5), HIGH(10);

    private final int weight;

    Level(int weight) {
      this.weight = weight;
    }

    int weight() {
      return weight;
    }
  }

  public static void main(String[] args) {
    Shape[] shapes = {new Circle(1.5), new Rect(2, 3.5)};
    for (Shape shape : shapes) {
      System.out.println(shape.describe());
    }
    for (Level level : Level.values()) {
      System.out.println(level + " " + level.weight());
    }
  }
}
Output
Circle area 7.07
Rect area 7.00
LOW 1
MEDIUM 5
HIGH 10

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1import java.util.Locale;
2
3class Main {
4 static abstract class Shape {
5 abstract double area();
6
7 String describe() {
8 return getClass().getSimpleName() + " area " + String.format(Locale.ROOT, "%.2f", area());
9 }
10 }
11
12 static class Circle extends Shape {
13 private final double radius;
14
15 Circle(double radius) {
16 this.radius = radius;
17 }
18
19 double area() {
20 return Math.PI * radius * radius;
21 }
22 }
23
24 static class Rect extends Shape {
25 private final double width;
26 private final double height;
27
28 Rect(double width, double height) {
29 this.width = width;
30 this.height = height;
31 }
32
33 double area() {
34 return width * height;
35 }
36 }
37
38 enum Level {
39 LOW(1), MEDIUM(5), HIGH(10);
40
41 private final int weight;
42
43 Level(int weight) {
44 this.weight = weight;
45 }
46
47 int weight() {
48 return weight;
49 }
50 }
51
52 public static void main(String[] args) {
53 Shape[] shapes = {new Circle(1.5), new Rect(2, 3.5)};
54 for (Shape shape : shapes) {
55 System.out.println(shape.describe());
56 }
57 for (Level level : Level.values()) {
58 System.out.println(level + " " + level.weight());
59 }
60 }
61}

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Every concrete shape must provide its own area.—
—
describe is written once in the base class and calls the subclass's area.—
—
An array of the abstract type can hold any subclass.shapes = [Circle, Rect]
—
Each call runs the area method of the actual object: π·1.5² = 7.07 and 2·3.5 = 7.00.shapes = [Circle, Rect]
Circle area 7.07
Rect area 7.00
Three constants, each created with a weight.shapes = [Circle, Rect]
Circle area 7.07
Rect area 7.00
values() returns the constants in declaration order.shapes = [Circle, Rect]
Circle area 7.07
Rect area 7.00
LOW 1
MEDIUM 5
HIGH 10

Behind the scenes

How Java processes this code

The Java compiler produces bytecode. The JVM loads the class and invokes its main method.

Cost and common mistakes

Each area call is O(1).

  • new Shape() does not compile because Shape is abstract.
  • An enum constructor is always private. You cannot create new enum instances with new.
  • Use Locale.ROOT with String.format so that the decimal separator does not change with the computer's language.

Try it yourself

Add a Triangle shape.

Reveal answer and reasoning

Create a class Triangle extends Shape with base and height fields and area() returning 0.5 * base * height; no existing code changes.

Further reading