我有一个 ENUM ,我在应用程序初始化时从数据库更新这些枚举值。然后使用enum all-over应用程序。
这样做的原因是,如果Value需要从数据库更改,那么只需在属性表中添加该值并更新它,以便在初始化枚举值得到更新时,其他枚举默认值将起作用。
示例: 我有这个枚举:
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; }
}
我用set方法更新Enum的值。
我想知道这样做是否正确。这种情况的正确方法是什么?
答案 0 :(得分:2)
Java enums mutability usecases and possibilities?
我不建议你让枚举值可变,它们应该几乎总是最终确定。
答案 1 :(得分:2)
枚举常量是单例,不可变对象可以在整个应用程序中使用mass
和radius
根据数据库更新,无法动态更改字段。
相反,可以创建内存缓存来存储mass
和radius
值,并且可以在每次数据库更新时刷新此内部Map
。但是,如果您需要使应用程序更具可伸缩性,那么您必须使用外部缓存(如Redis)来存储PlanetStats对象,而不是内部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);
}
}
答案 2 :(得分:1)
对于使用setter的更新,字段不应为final
。
就是这样。其他论点没有实际意义。如果你有一个最终的命名值范围,枚举就可以了。
immutable 类(带有final字段)本来会更好,但是除非使用静态初始化,否则数据库无法实现。在初始化期间需要数据库可能是可以接受的,但通常应尽可能避免,并且当它不是嵌入式数据库时。
答案 3 :(得分:0)
即使你可以改变枚举的状态 - 我也不推荐它。
枚举是单身,这意味着
您的状态更改应该是线程安全的,因为一个线程可能会使用枚举,而另一个线程会更改它的状态。
状态未像其他对象的状态那样被序列化。如果你使用序列化,直接或通过其他框架或技术,如RMI或spring remoting,状态更改将无法正常工作。
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());
}
打印
2.0
反序列化Planet
的质量属性不具有Planet
序列化时的值。
我也在序列化旁路部分的Singleton implementation pitfalls博客中讨论了此问题。
PS:我使用了来自commons-lang3的SerializationUtils