Sealed Classes and Interfaces in Java 21

Today, we’ve got an incredibly exciting article for you about sealed interfaces 🤩 and sealed classes 🔒 in Java 21! 🐱‍💻✨ Get ready to dive into the fascinating world of Java’s powerful new features! 🚀🔍

Java 21 introduces sealed classes and interfaces, available from Java SE 17 onwards, which are perfect for handling API responses and error management 🎯, and for categorizing data structures 📊🔗. These tools enhance your code’s safety 🛡️, clarity 🧩, and maintainability 🛠️, making Java an even more robust choice for backend development! 💻🎉

Sealed Classes: Streamlining Responses and Error Handling

Sealed classes in Java allow for defining a restricted hierarchy of classes that represent various states or types of responses. This feature is particularly useful for modeling API responses, where different outcomes such as success, error, and loading states need to be handled distinctly.

Example: API Response Sealed Class

public sealed class ApiResponse<T> permits ApiResponse.Success, ApiResponse.Error, ApiResponse.Loading {
    public static final class Success<T> extends ApiResponse<T> {
        private final T data;
        public Success(T data) {
            this.data = data;
        }
        public T getData() {
            return data;
        }
    }

    public static final class Error extends ApiResponse<Nothing> {
        private final String message;
        public Error(String message) {
            this.message = message;
        }
        public String getMessage() {
            return message;
        }
    }

    public static final class Loading extends ApiResponse<Nothing> {}
}

In this example, ApiResponse is a sealed class that can represent:

  • Success with data of type T
  • Error with an error message
  • Loading to indicate an ongoing process

Usage Example:

public ApiResponse<String> fetchData() {
    // Simulate API call
    return new ApiResponse.Success<>("Hello, World!");
}

public void handleResponse(ApiResponse<String> response) {
    if (response instanceof ApiResponse.Success) {
        System.out.println("Success: " + ((ApiResponse.Success<String>) response).getData());
    } else if (response instanceof ApiResponse.Error) {
        System.out.println("Error: " + ((ApiResponse.Error) response).getMessage());
    } else if (response instanceof ApiResponse.Loading) {
        System.out.println("Loading...");
    }
}

Sealed Interfaces: Organizing Data Structures

Sealed interfaces are beneficial for categorizing related data structures without adding behavior to them. They enforce that all implementing classes are defined within the same module, promoting a structured and maintainable codebase.

Example: Database Entity Types

public sealed interface Entity permits User, Product, Order {}

public final class User implements Entity {
    private final long id;
    private final String name;

    public User(long id, String name) {
        this.id = id;
        this.name = name;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}

public final class Product implements Entity {
    private final long id;
    private final String name;
    private final double price;

    public Product(long id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }
}

public final class Order implements Entity {
    private final long id;
    private final List<Product> items;

    public Order(long id, List<Product> items) {
        this.id = id;
        this.items = items;
    }

    public long getId() {
        return id;
    }

    public List<Product> getItems() {
        return items;
    }
}

Usage Example:

public void processEntity(Entity entity) {
    if (entity instanceof User) {
        System.out.println("Processing User: " + ((User) entity).getName());
    } else if (entity instanceof Product) {
        System.out.println("Processing Product: " + ((Product) entity).getName());
    } else if (entity instanceof Order) {
        System.out.println("Processing Order with " + ((Order) entity).getItems().size() + " items");
    }
}

Benefits for Backend Development

  • Type Safety: Sealed classes and interfaces ensure that all possible states are accounted for, reducing runtime errors.
  • Code Clarity: By grouping related types and explicitly defining their structure, code becomes more understandable and maintainable.
  • Error Handling: Sealed classes facilitate clear and structured error handling, distinguishing between different error scenarios effectively.

Conclusion

Java 21’s sealed classes and interfaces are valuable assets for backend developers, providing tools that enhance code safety, clarity, and maintainability. Their ability to manage data structures and API responses efficiently makes Java a robust choice for backend development.

Happy coding! 🖥️

Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *

×