Back to Java
2026-03-015 min read

abstract

Learn abstract step by step with clear examples and exercises.

Title: Understanding and Implementing Abstract Classes in Java

Why This Matters

In this lesson, we'll explore abstract classes in Java—a powerful tool for creating flexible class hierarchies and enforcing good object-oriented design principles. You'll learn how to declare an abstract class, create concrete subclasses, and understand when and why you should use abstract classes in your programs. This knowledge will help you write cleaner, more maintainable code, and prepare you for real-world programming scenarios and job interviews.

Prerequisites

To follow this lesson, you should have a good understanding of the following:

  • Basic Java syntax (variables, methods, classes)
  • Inheritance and polymorphism in Java
  • Interfaces in Java

Core Concept

An abstract class is a special type of class that cannot be instantiated on its own. Instead, it serves as a base for other classes, providing common functionality that those subclasses can inherit and build upon. An abstract class may contain both concrete (implemented) methods and abstract (declared but not implemented) methods.

To declare an abstract class in Java, use the abstract keyword before the class name:

public abstract class AbstractClass {
// ...
}

An abstract method is a method that is declared without any implementation—only its signature (name, return type, and parameters) are provided. In an abstract class, at least one method must be abstract. To declare an abstract method, use the abstract keyword before the method declaration:

public abstract void myAbstractMethod();

Concrete subclasses of an abstract class must provide implementations for all abstract methods in their superclass. If a subclass does not provide an implementation for an abstract method, it too must be declared as abstract.

Here's an example of an abstract class and two concrete subclasses:

public abstract class Animal {
private String name;

public Animal(String name) {
this.name = name;
}

public String getName() {
return name;
}

public abstract void makeSound();
}

public class Dog extends Animal {
public Dog(String name) {
super(name);
}

@Override
public void makeSound() {
System.out.println("Woof!");
}
}

public class Cat extends Animal {
public Cat(String name) {
super(name);
}

@Override
public void makeSound() {
System.out.println("Meow!");
}
}

In this example, Animal is an abstract class with a constructor, a getter method, and an abstract method makeSound(). The Dog and Cat classes are concrete subclasses that inherit from the Animal class and provide their own implementations for the makeSound() method.

Worked Example

Let's create a simple example using abstract classes to represent different shapes with common properties like area and perimeter.

First, we'll define an abstract class Shape:

public abstract class Shape {
private double width;
private double height;

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

public double getWidth() {
return width;
}

public double getHeight() {
return height;
}

public abstract double calculateArea();
public abstract double calculatePerimeter();
}

Next, we'll create concrete subclasses for Rectangle, Circle, and Triangle:

public class Rectangle extends Shape {
public Rectangle(double width, double height) {
super(width, height);
}

@Override
public double calculateArea() {
return width * height;
}

@Override
public double calculatePerimeter() {
return 2 * (width + height);
}
}

public class Circle extends Shape {
private final double PI = Math.PI;
private double radius;

public Circle(double radius) {
super(radius, radius); // use radius for both width and height
this.radius = radius;
}

@Override
public double calculateArea() {
return PI * radius * radius;
}

@Override
public double calculatePerimeter() {
return 2 * PI * radius;
}
}

public class Triangle extends Shape {
private double base;
private double height;

public Triangle(double base, double height) {
super(base, height); // use base for width and height/2 for height
this.base = base;
this.height = height / 2;
}

@Override
public double calculateArea() {
return 0.5 * base * height;
}

@Override
public double calculatePerimeter() {
return base + Math.sqrt(Math.pow(base, 2) + Math.pow(height, 2)) + height;
}
}

Now we can create instances of these classes and calculate their areas and perimeters:

public static void main(String[] args) {
Shape rectangle = new Rectangle(4, 5);
System.out.println("Rectangle area: " + rectangle.calculateArea());
System.out.println("Rectangle perimeter: " + rectangle.calculatePerimeter());

Shape circle = new Circle(3);
System.out.println("Circle area: " + circle.calculateArea());
System.out.println("Circle perimeter: " + circle.calculatePerimeter());

Shape triangle = new Triangle(4, 6);
System.out.println("Triangle area: " + triangle.calculateArea());
System.out.println("Triangle perimeter: " + triangle.calculatePerimeter());
}

Common Mistakes

  1. Forgetting to make a class abstract when it should be: If a class is intended to serve as a base for other classes but doesn't have any abstract methods, it should still be declared as abstract.
  2. Not providing implementations for all abstract methods in concrete subclasses: Concrete subclasses must provide an implementation for every abstract method from their superclass. Failing to do so will result in a compile-time error.
  3. Calling abstract methods directly on abstract classes: Since abstract classes cannot be instantiated, you can't call abstract methods on them directly. Instead, create an instance of a concrete subclass and call the method on that object.
  4. Declaring a class as both abstract and final: You cannot make a class both abstract (meaning it cannot be instantiated) and final (meaning it cannot be subclassed). If you want to prevent a class from being subclassed, simply don't declare any abstract methods.
  5. Using the new keyword with an abstract class: Since abstract classes cannot be instantiated, using the new keyword with them will result in a compile-time error. Instead, create instances of concrete subclasses.

Practice Questions

  1. Create an abstract class Vehicle with abstract methods for accelerating and braking. Define two concrete subclasses: Car and Motorcycle. Implement the accelerate and brake methods for each subclass.
  2. Design an abstract class Account representing a bank account with properties like balance, interest rate, and account number. Create two concrete subclasses: CheckingAccount and SavingsAccount. Implement methods to deposit, withdraw, and calculate the monthly interest for each subclass.
  3. Create an abstract class Shape3D with abstract methods for calculating surface area and volume. Define three concrete subclasses: Sphere, Cube, and Cylinder. Implement the necessary methods for each subclass to calculate their respective surface areas and volumes.

FAQ

  1. Can I have both abstract and non-abstract methods in an abstract class? Yes, you can have both abstract and non-abstract (concrete) methods in an abstract class. The concrete methods provide common functionality that all subclasses inherit and build upon.
  2. What happens if a concrete subclass doesn't implement all the abstract methods from its superclass? If a concrete subclass does not provide an implementation for all the abstract methods from its superclass, it too must be declared as abstract.
  3. Can I instantiate an abstract class? No, you cannot instantiate an abstract class directly because it is intended to serve as a base for other classes. Instead, create instances of concrete subclasses derived from the abstract class.
  4. What's the difference between an interface and an abstract class in Java? Both interfaces and abstract classes can contain abstract methods, but there are some key differences:
  • An interface cannot have instance variables or implementations for its methods; an abstract class can have both.
  • A class can extend only one abstract class but can implement multiple interfaces.
  • Interfaces are more commonly used to define a contract that multiple unrelated classes can implement, while abstract classes are often used as base classes in hierarchies of related classes.
abstract | Java | XQA Learn