杰瑞科技汇

Java enum 如何转为 int?

Of course! Converting a Java enum to an int is a common task. There are two primary ways to do this, each with its own use cases and best practices.

Java enum 如何转为 int?-图1
(图片来源网络,侵删)
  1. Using the ordinal() method (The Simple but Risky Way)
  2. Using a custom int field (The Robust and Recommended Way)

Let's break them down.


Method 1: Using ordinal() (Simple but Risky)

Every enum value has an ordinal() method that returns its zero-based position in the enum declaration.

public enum Day {
    MONDAY,    // ordinal() -> 0
    TUESDAY,   // ordinal() -> 1
    WEDNESDAY, // ordinal() -> 2
    THURSDAY,  // ordinal() -> 3
    FRIDAY,    // ordinal() -> 4
    SATURDAY,  // ordinal() -> 5
    SUNDAY     // ordinal() -> 6
}
public class Main {
    public static void main(String[] args) {
        Day today = Day.WEDNESDAY;
        // Get the int value using ordinal()
        int dayAsInt = today.ordinal();
        System.out.println("The enum is: " + today);
        System.out.println("Its ordinal int value is: " + dayAsInt); // Output: 2
    }
}

Why ordinal() is Generally Discouraged for Persistent Data

While ordinal() is convenient, it has a major drawback: it's tied to the order of declaration in the source code.

If you change the order of the enum constants, the int values change. This can lead to subtle and hard-to-find bugs, especially if you are storing these int values in a database, file, or sending them over a network.

Java enum 如何转为 int?-图2
(图片来源网络,侵删)

Bad Example (The Risk):

Imagine you store Day.MONDAY.ordinal() (which is 0) in a database.

// In version 1 of your application
public enum Day {
    MONDAY,    // ordinal() -> 0
    TUESDAY,   // ordinal() -> 1
    // ...
}
// You store 0 for Monday in the database.
// In version 2, you decide to add a new day at the top
public enum Day {
    HOLIDAY,   // NEW! ordinal() -> 0
    MONDAY,    // ordinal() -> 1  <-- VALUE CHANGED!
    TUESDAY,   // ordinal() -> 2
    // ...
}
// Now, when you read the `0` from the database, it will be incorrectly interpreted as `HOLIDAY`.

Because of this fragility, you should avoid using ordinal() for anything other than temporary, in-memory purposes, like implementing a switch statement.


Method 2: Using a Custom int Field (Robust and Recommended)

This is the best practice for almost all scenarios. You assign a specific, meaningful int value to each enum constant. This value is independent of the declaration order.

Java enum 如何转为 int?-图3
(图片来源网络,侵删)

Step-by-Step Implementation

Define the enum with a constructor and a field.

The constructor takes the int value, and the field stores it.

public enum Planet {
    // Enum constants are instances of the enum class
    MERCURY(1),
    VENUS(2),
    EARTH(3),
    MARS(4),
    JUPITER(5),
    SATURN(6),
    URANUS(7),
    NEPTUNE(8);
    // A field to hold the int value
    private final int planetCode;
    // A private constructor to initialize the enum constants
    private Planet(int planetCode) {
        this.planetCode = planetCode;
    }
}

Provide a public "getter" method to access the int value.

public enum Planet {
    // ... constants from above ...
    private final int planetCode;
    private Planet(int planetCode) {
        this.planetCode = planetCode;
    }
    // The public getter method
    public int getPlanetCode() {
        return this.planetCode;
    }
}

Use the getter to get the int value.

public class Main {
    public static void main(String[] args) {
        Planet myPlanet = Planet.EARTH;
        // Get the int value using our custom getter
        int planetAsInt = myPlanet.getPlanetCode();
        System.out.println("The enum is: " + myPlanet);
        System.out.println("Its custom int value is: " + planetAsInt); // Output: 3
    }
}

Advantages of the Custom Field Approach

  • Stability: The int value is explicitly defined and won't change if you reorder the enum constants.
  • Readability: getPlanetCode() is much more descriptive than ordinal(). It's clear what the number represents.
  • Flexibility: You can use any int value you want, not just 0, 1, 2, .... For example, you could use database IDs: EARTH(5003).
  • Safety: It prevents the bugs that can arise from using ordinal() for persistent data.

Bonus: Converting an int back to an enum

Often, you'll need to do the reverse: convert an int back to its corresponding enum. The safest way to do this is by iterating through the enum values and comparing them.

public class Main {
    public static void main(String[] args) {
        int codeToFind = 4;
        Planet foundPlanet = intToPlanet(codeToFind);
        if (foundPlanet != null) {
            System.out.println("Found planet for code " + codeToFind + ": " + foundPlanet);
        } else {
            System.out.println("No planet found for code " + codeToFind);
        }
    }
    /**
     * Safely converts an int to a Planet enum.
     * @param code The int code to look for.
     * @return The corresponding Planet enum, or null if not found.
     */
    public static Planet intToPlanet(int code) {
        for (Planet planet : Planet.values()) {
            if (planet.getPlanetCode() == code) {
                return planet;
            }
        }
        return null; // Or throw an exception: throw new IllegalArgumentException("Invalid planet code: " + code);
    }
}

Summary: Which Method to Use?

Scenario Recommended Method Why?
Switch statements ordinal() It's concise and perfect for this temporary, in-memory use case.
Storing in a database Custom int field Values are stable and won't break if you add/remove/reorder constants.
Serialization (JSON, XML) Custom int field Ensures data integrity across different versions of your application.
API communication Custom int field Provides a stable contract between the client and server.
General purpose Custom int field It's safer, more readable, and more robust. It's the professional standard.
分享:
扫描分享到社交APP
上一篇
下一篇