Back to Blog
Java

Java Abstract Class: When to Use It and How to Write One

java abstract class: Understand Java abstract classes: syntax, abstract methods, constructors, and when to choose an abstract class over an interface.

abstract classjava inheritanceinterface vs abstract classtemplate method patternjava oop
Illustration of a Java abstract class as a template for subclasses, with abstract methods and concrete implementations.

java abstract class requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

An abstract class in Java is a class that cannot be instantiated directly. It is declared with the abstract keyword and typically contains one or more abstract methods—methods that have a signature but no implementation. Subclasses are responsible for providing the implementation. This design lets you define a common contract and shared state for a group of related classes while leaving specific behavior to each subclass. n## Declaring an Abstract Class and Abstract Methods aTo declare an abstract class, you place the abstract modifier before the class keyword. Abstract methods are declared with the abstract modifier and end with a semicolon instead of a method body.

public abstract class PaymentProcessor { public abstract void processPayment(double amount); }

The processPayment method has no body. Any concrete subclass must implement it. If a subclass does not implement all abstract methods, that subclass must also be declared abstract.

Abstract Methods: Contract Without Implementation

An abstract method defines the signature that all subclasses must follow, but it says nothing about how the method should behave. This is useful when you have a common operation that varies significantly between subclasses. For example, a PaymentProcessor might have subclasses CreditCardProcessor and PayPalProcessor, each with its own processPayment implementation.

public class CreditCardProcessor extends PaymentProcessor { @Override public void processPayment(double amount) { // charge the credit card } }

The abstract method forces every subclass to provide the implementation, preventing a situation where a developer forgets to implement a required behavior.

Constructors in Abstract Classes

Even though you cannot instantiate an abstract class directly, it can have constructors. These constructors are called when a subclass instance is created, using the super() call. This is important for initializing shared fields that the abstract class declares.

public abstract class PaymentProcessor { private String merchantId; public PaymentProcessor(String merchantId) { this.merchantId = merchantId; } public abstract void processPayment(double amount); } public class CreditCardProcessor extends PaymentProcessor { public CreditCardProcessor(String merchantId) { super(merchantId); } @Override public void processPayment(double amount) { // use merchantId } }

The constructor in the abstract class runs before the subclass constructor body. This ensures that shared state is initialized consistently across all subclasses.

Abstract Class vs Interface: Key Differences

Both abstract classes and interfaces define contracts, but they differ in several ways. In Java 8 and later, interfaces can have default and static methods, which narrows the gap. However, abstract classes still offer features that interfaces do not.

FeatureAbstract ClassInterface
Instance fieldsCan have non-constant instance fieldsFields are implicitly public static final
ConstructorsCan have constructorsCannot have constructors
Access modifiersMethods can be public, protected, or privateMethods are implicitly public (before Java 9)
Multiple inheritanceA class can extend only one abstract classA class can implement multiple interfaces
StateCan maintain state across methodsCannot maintain instance state (except via default methods with limitations)

Use an abstract class when you need to share code and state among closely related classes. Use an interface when you want to define a capability that can be implemented by unrelated classes.

Access Modifiers and Visibility

Abstract methods can be public or protected. They cannot be private because a private method is not visible to subclasses and cannot be overridden. Similarly, an abstract method cannot be final because final prevents overriding. Static methods cannot be abstract either, because static methods belong to the class itself and are not inherited in the same way.

public abstract class Base { protected abstract void validate(); // allowed // private abstract void invalid(); // compile error // final abstract void invalid(); // compile error // static abstract void invalid(); // compile error }

Common Mistakes and Edge Cases

A common mistake is trying to instantiate an abstract class. The compiler rejects this with an error. Another mistake is forgetting to implement an abstract method in a concrete subclass, which also produces a compile-time error. A less obvious issue is that an abstract class can have concrete methods, and those methods can call abstract methods. This is a powerful pattern, but it means the abstract method is invoked before the subclass constructor finishes, which can lead to unexpected behavior if the subclass method relies on fields that are not yet initialized.

public abstract class Base { public Base() { init(); // calls subclass method before subclass constructor body } protected abstract void init(); }

In this example, init() is called during the base constructor. If a subclass overrides init() and accesses its own fields, those fields are still null because the subclass constructor has not run yet. This is a subtle bug that can be avoided by not calling abstract methods from constructors.

Performance and Maintainability Considerations

From a performance standpoint, calling an abstract method uses dynamic dispatch, which is slightly slower than a direct call, but the difference is negligible in most applications. The bigger cost is often the added layer of abstraction. Overusing abstract classes can make code harder to follow, especially when the hierarchy is deep. On the maintainability side, abstract classes reduce duplication by centralizing shared logic. They also make the contract explicit: any new subclass must implement the abstract methods, which helps enforce consistency across a codebase.

A Practical Example: Template Method Pattern

A common use of an abstract class is the template method pattern. The abstract class defines the skeleton of an algorithm, and subclasses fill in specific steps.

public abstract class DataParser { public final void parse(String filePath) { openFile(filePath); readData(); closeFile(); } protected abstract void openFile(String filePath); protected abstract void readData(); protected abstract void closeFile(); }

Subclasses implement the three steps, while the parse method remains fixed. This keeps the algorithm structure in one place and lets each subclass handle its own file format. The final modifier on parse prevents subclasses from changing the algorithm order, which is often desirable in this pattern.

java abstract class: Practical Usage and Code Examples | RYUSLOG DEV