1

I have one ENUM and I am updating those enum value from database on initialization of application. And then using that enum all-over application.

The reason to do so is that if Value need to change from database then just add that value in property table and update it, so that on initialization enum values got updated else enum default value will be working.

Example : I have this enum :

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass() { return mass; }
    private double radius() { return radius; }

    private void setMass(double mass) { this.mass = mass; }
    private void setRadius(double radius) { this.radius = radius; }

}

And I update values of Enum with set methods.

I would like to know whether doing this is correct or not. What is the right way to do for such scenarios?

vinS
  • 1,417
  • 5
  • 24
  • 37
murtaza.webdev
  • 3,523
  • 4
  • 22
  • 32

4 Answers4

2

Java enums mutability usecases and possibilities?

i would not advise you to make enum values mutable, they should almost always be finalized.

Ben Sch
  • 104
  • 1
  • 6
2

Enum constants are singleton and immutable objects can be used all over the application and mass and radius fields cannot be changed on the fly according to database updates.

Instead, in-memory cache can be created to store mass and radius values and this internal Map can be refreshed on every database update. But if you need to make your application more scalable, then you have to use external cache such Redis to store PlanetStats objects instead in internal Map.

enum Planet {
    MERCURY,
    VENUS,
    EARTH
}

class PlanetStats {
    private final double mass;
    private final double radius;

    PlanetStats(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    public double getMass() {
        return mass;
    }

    public double getRadius() {
        return radius;
    }
}


class PlanetCache {

    private final Map<Planet, PlanetStats> stats = new ConcurrentHashMap<>();

    // can be invoked on database update for each Planet object change
    public void refresh(Planet planet, PlanetStats planetStats) {
        stats.put(planet, planetStats);
    }

    // can be invoked to fetch PlanetStats for specified Planet
    public PlanetStats getPlanetStats(Planet planet) {
        return stats.get(planet);
    }
}
baybatu
  • 81
  • 8
1

For an update with a setter the fields should not be final.

That is all. Other arguments are moot. If you have a final range of named values, an enum is fine.

An immutable class (with final fields) would have been better, but not achievable with a database unless with a static initialisation. Needing a database during initialisation may be acceptable, but in general should be avoided when possible and when it is not an embedded database.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
0

Even if you can change the state of an enum - I would not recommend it.

Enums are singletons and this means that

  1. your state changes should be thread-safe, because one thread might use the enum while another changes it's state.

  2. the state is not serialized like the state of other objects. If you use serialization, either direct or through another framework or technology like RMI or springs remoting, the state changes will not work as you might expect.

    E.g.

    public static void main(String[] args) {
        Planet mercury = Planet.MERCURY;
    
        mercury.setMass(1.0);
    
        byte[] mercurySerialized = SerializationUtils.serialize(mercury);
    
        mercury.setMass(2.0);
    
        Planet mercuryDeserialized = SerializationUtils.deserialize(mercurySerialized);
    
        System.out.println(mercuryDeserialized.mass());
    }
    

    It prints

    2.0
    

    The mass property of the deserialized Planet doesn't have the value that the Planet had when it was serialized.

    I also discuss this in my blog Singleton implementation pitfalls in the section serialization bypass.

PS: I use SerializationUtils from commons-lang3

René Link
  • 48,224
  • 13
  • 108
  • 140