Explain Codes LogoExplain Codes Logo

Using Enum values as String literals

java
enum-usage
advanced-java
best-practices
Alex KataevbyAlex Kataev·Sep 29, 2024
TLDR

For direct Enum to String conversions, use .name():

public enum Color { RED, GREEN, BLUE; } // Who spilled paint on my strings? String red = Color.RED.name(); // "RED"

For custom String representations, override .toString():

public enum Color { RED, GREEN, BLUE; @Override public String toString() { // Anything looks good when it's lowercased, right? return name().toLowerCase(); } } // Hulk's favorite color String green = Color.GREEN.toString(); // "green"

To get consistent String representation, centralize your enums:

public enum Status { OPEN("Open"), IN_PROGRESS("In Progress"), CLOSED("Closed"); private final String label; private Status(String label) { this.label = label; } @Override public String toString() { // Uniformity is beauty return label; } } String status = Status.OPEN.toString(); // "Open"

Convert Strings to Enums with .valueOf():

Status status = Enum.valueOf(Status.class, "OPEN"); // Status.OPEN

Advanced Enum Usage

Injecting more context with Enum constructors

Craft a more descriptive Enum using constructors:

public enum ErrorCode { NOT_FOUND(404, "Not Found"), SERVER_ERROR(500, "Server Error"); private final int code; private final String description; ErrorCode(int code, String description) { this.code = code; this.description = description; } public int getCode() { return code; } public String getDescription() { return description; } }

Tips: If you want just the description, .getDescription() has you covered. To get both - ErrorCode.SERVER_ERROR isn't too lazy to spill all the beans!

Enum Alternatives — Interface constants

An interface can play the constant's gathering card. Here's a related set of HttpStatusCodes as constants:

public interface HttpStatusCodes { int OK = 200; int NOT_FOUND = 404; // ... }

Remember: It's just constants, no enum functionality. So, type safety? And advanced features? They've left the chat.

Cutting down toString() calls

Don't make .toString() your workhorse. Direct property access saves some CPU clock cycles. Example:

// toString() is called by default, even if it's on a break System.out.println(ErrorCode.SERVER_ERROR);

Are direct accesses better? Try .getDescription() on for size:

// ErrorCode.SERVER_ERROR served some well-deserved rest System.out.println(ErrorCode.SERVER_ERROR.getDescription());

Closet Organizer — Centralized Enum handling

Loose String literals scattered in your code? Use a utility class to manage them:

public class EnumUtils { public static String getEnumDescription(Enum<?> e) { try { // Peek into the closet to find the description return (String) e.getClass().getDeclaredField(e.name()).getAnnotation(Description.class).value(); } catch (Exception ex) { // Nothing? Return the name then. return e.name(); } } // Usage: @Description("Open Status") OPEN, // ... }

Enum proxies — Static final variables

Need to squeeze out performance? Or skip Enum functionalities? Static final constants are your friend:

public final class StatusConstants { public static final String OPEN = "Open"; // This class just doesn't want to mingle private StatusConstants() {} }

Keeping it maintainable

Does .toString() add value? Or is it merely a cosmetic frill? In your overrides, aim for clarity and usefulness:

public enum Direction { NORTH, SOUTH, EAST, WEST; @Override public String toString() { switch(this) { case NORTH: return "N"; case SOUTH: return "S"; case EAST: return "E"; case WEST: return "W"; default: throw new AssertionError("Unknown cardinal point: " + this); } } } // This brings all the cardinal points to the chess board!