Syntax
abstract class ClassName {\n abstract returnType methodName();\n}Examples
Basic Abstract Class
Defining a base class that mixes concrete and abstract methods.
public abstract class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public abstract void makeSound(); // no body - subclasses must implement
public void sleep() { // concrete method, shared by all subclasses
System.out.println(name + " is sleeping");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void makeSound() {
System.out.println(name + " says: Woof!");
}
}
// Animal a = new Animal("Generic"); // Error - can't instantiate abstract class
Dog dog = new Dog("Rex");
dog.makeSound();
dog.sleep();Enforcing a Common Structure
Multiple subclasses implementing the same abstract method differently.
abstract class Employee {
protected String name;
protected double baseSalary;
public Employee(String name, double baseSalary) {
this.name = name;
this.baseSalary = baseSalary;
}
public abstract double calculateBonus();
public double totalPay() {
return baseSalary + calculateBonus();
}
}
class Manager extends Employee {
public Manager(String name, double baseSalary) {
super(name, baseSalary);
}
@Override
public double calculateBonus() {
return baseSalary * 0.2;
}
}
class Developer extends Employee {
public Developer(String name, double baseSalary) {
super(name, baseSalary);
}
@Override
public double calculateBonus() {
return baseSalary * 0.1;
}
}
Employee m = new Manager("Fola", 60000);
System.out.println(m.totalPay()); // 72000.0Abstract Class vs Interface
A quick illustration of when each is more appropriate.
// Interface: unrelated classes sharing a capability, no shared state
interface Flyable {
void fly();
}
// Abstract class: closely related classes sharing state AND behavior
abstract class Bird {
protected String species;
public Bird(String species) {
this.species = species;
}
public abstract void layEggs();
public void breathe() {
System.out.println(species + " is breathing");
}
}
class Eagle extends Bird implements Flyable {
public Eagle() {
super("Eagle");
}
public void layEggs() {
System.out.println("Eagle laying eggs");
}
public void fly() {
System.out.println("Eagle soaring high");
}
}Best practices
- Use an abstract class when subclasses share both state (fields) and some common implemented behavior, not just a method signature
- Use an interface instead when unrelated classes just need to share a capability, with no shared fields or implementation
- A class can only extend one abstract class but can implement multiple interfaces - factor that into your design choice
- Make a method abstract only when every subclass genuinely needs its own distinct implementation - otherwise provide a sensible default in the abstract class itself
At a glance
- Purpose
- General-purpose application development
- File extension
- .java
- Runs in
- Java Virtual Machine
- Usually used with
- JDK and Java libraries
Specifications & further reading
Related Java documentation
Classes
Classes in Java are blueprints for creating objects, defining their properties (fields) and behaviors (methods). Java is a strictly object-oriented language where everything is encapsulated within classes. A class serves as a template that specifies what data an object will store and what operations it can perform.Interfaces
An interface defines a contract of methods that implementing classes must provide, without specifying how those methods work internally. Unlike a class, an interface cannot be instantiated directly - it only declares what a class can do, not how. A class uses the 'implements' keyword to fulfill an interface's contract, and a single class can implement multiple interfaces, which is Java's way of achieving a form of multiple inheritance.Constructors
A constructor is a special method that runs automatically when an object is created with 'new', typically used to initialize the object's fields. A constructor shares its name with the class and has no return type, not even void. Java supports constructor overloading, letting a class offer multiple ways to construct an object, and constructor chaining with this(...), where one constructor calls another in the same class.Access Modifiers
Access modifiers control the visibility of classes, fields, and methods from other parts of a program. Java has four levels: public (accessible from anywhere), protected (accessible within the same package and by subclasses), default/package-private (accessible only within the same package, used when no modifier is written), and private (accessible only within the declaring class itself).
Classes in Java are blueprints for creating objects, defining their properties (fields) and behaviors (methods). Java is a strictly object-oriented language where everything is encapsulated within classes. A class serves as a template that specifies what data an object will store and what operations it can perform.Interfaces
An interface defines a contract of methods that implementing classes must provide, without specifying how those methods work internally. Unlike a class, an interface cannot be instantiated directly - it only declares what a class can do, not how. A class uses the 'implements' keyword to fulfill an interface's contract, and a single class can implement multiple interfaces, which is Java's way of achieving a form of multiple inheritance.Constructors
A constructor is a special method that runs automatically when an object is created with 'new', typically used to initialize the object's fields. A constructor shares its name with the class and has no return type, not even void. Java supports constructor overloading, letting a class offer multiple ways to construct an object, and constructor chaining with this(...), where one constructor calls another in the same class.Access Modifiers
Access modifiers control the visibility of classes, fields, and methods from other parts of a program. Java has four levels: public (accessible from anywhere), protected (accessible within the same package and by subclasses), default/package-private (accessible only within the same package, used when no modifier is written), and private (accessible only within the declaring class itself).