14

I don't know if I'm the only one to know that, but the values of an enum are not implicitly final and can be modified.

  enum EnumTest {
    TOTO("TOTO 1"),
    TATA("TATA 2"),
    ;

    private String str;

    private EnumTest(String str) {
      this.str = str;
    }

    @Override
    public String toString() {
      return str;
    }
  }

  public static void main(String[] args) {
    System.out.println(EnumTest.TATA);
    EnumTest.TATA.str = "newVal";
    System.out.println(EnumTest.TATA);
  }

TATA 2
newVal

These values are oftenly initialized at instance creation (TOTO("TOTO 1")) but, except myself, I've never seen anyone using the final keyword for enum variables that should be immutable. That's not the point of the question, just wondering if I'm the only one aware of this.


What I'd like to know is if there was any usecase to create mutable enums?

And I'd also like to know the limits of what we can do with enums (good practice or not). I've not tested it, but maybe an enum can be injected with Spring beans? At least it seems we can annotate each instance (@Deprecated works fine for exemple), and also the methods.

Sebastien Lorber
  • 89,644
  • 67
  • 288
  • 419

8 Answers8

11

One possible usecase would be lazy initialization (calculate some field values when they are first used, if often they are not used at all), or a "normal" mutable singleton object (like a registry or such).

In most cases, though, enum objects should be immutable, and their fields be final.

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
9

While you point out an interesting fact here, as far as I'm concerned, there is no usecase for mutable enum fields. There are many reasons why making use of this language "feature" ("bug"?) would be a bad idea, not least of which is the potential for confusing other developers.

Alex D
  • 29,755
  • 7
  • 80
  • 126
  • 4
    I agree in that enums are generally assumed to be immutable and thereby creating mutable enums could lead to misuse. I would suggest that mutable values associated with enums would best be help in an `EnumMap`. That said, I think saying there is "no usecase" is too strong. Enums in practice represent an extension of the singlton pattern (a fixed number of instances) and with that in mind could be used like any other class. I again reiterate that MOST developers are used to thinking of them as IMMUTABLE and therefore mutable enums could lead to maintenance issues. – John B Oct 22 '12 at 16:57
  • Thank god as they are assumed immutabl there is generally no setter :) – Sebastien Lorber Oct 22 '12 at 20:10
  • @JohnB, if you can think of a good example of a situation where using an enum with mutable fields is arguably better than any alternative, I would appreciate seeing it as a separate answer. But my answer is still: as far as I'm concerned, there is **no** usecase, at least not a usecase which couldn't be better served with an ordinary `class`. You are right about what enums are "in practice", but conceptually they are closer to a `boolean` (which has a fixed set of 2 possible values) or an `int` (fixed set of 2^32-1 possible values). Can you imagine having mutable fields on `true`? – Alex D Oct 22 '12 at 21:23
3

In response to Alex D's answer and comment, I am taking his suggestion of posting a possible use case. Let's take the old standard enum example of planets from which gravity, etc can be calculated. Imagine that you wanted to maintain the number of human colonies on each planet. Yes you could use a EnumMap, but I could see a case where more and more mutable fields could be needed and having either a seperate map for each value or a separate class to hold the mutable values associated with an enum would be counter-intuitive.

As I stated in my comments, in general I believe enums usually are and should be immutable but I feel that stating that there are no use cases is too strong.

John B
  • 32,493
  • 6
  • 77
  • 98
2

I see no reason to forbid the use of mutable fields in enums. One uses an enum to state that the value of the type belongs to one of a finite (and known) set of possibilities. It does not imply that those values can not have properties that evolve over time.

Some have asked for use cases for such a scenario. One example would be to use an enum type such as ErrorCategory, which would classify an error to one of any number of predefined categories (eg: DocumentationError, SemanticError, LayoutError...).

Suppose those ErrorCategories have properties such as requiresInstantIntervention or shouldFailBuild. I can imagine that the value of those properties could change over time or that they can be user-configurable.

I realize that there are (many) other ways of implementing this (such as indeed EnumMaps mentioned above) and one can always argue about style, but for me, such a use of enums is not wrong in itself. As enums are reference types in java, behaviour of == remains the same as if there were no mutable properties in the first place.

ASGM
  • 11,051
  • 1
  • 32
  • 53
Yves V.
  • 775
  • 1
  • 7
  • 20
2

An enum instance is a public static final Field of the enum class. So if it's mutable, you may modify its state in another thread. This may not be what you want and may cause problems if you don't realize this.

Louis CAD
  • 10,965
  • 2
  • 39
  • 58
Adrian Liu
  • 385
  • 3
  • 13
1

Correct me if I am wrong but an Enum is the easiest (and more importantly perhaps the safest) way in Java to actually have a true singleton throughout the lifetime of the application (if we cannot use the CDI), as using the standard static getInstance() method pattern could still produce multiple instances of the same class if implemented too naively.

[Likewise implementing the Serializable could also potentially lead to producing more than just one instance, whereas the Enum already takes care of it for us without unexpected results and boilerplate.]

Also, the documentation says clearly that the Enum type is so much more than just constants. So I would say that whenever it's absolutely necessary to have a true singleton in the app, an Enum (even mutable), might be considered a fair use.

However, it seems to me that this question inevitably tends to be a bit on the opinionated side and cannot be answered completely unbiased as there are developers who favor immutability (and I am not saying that there are not good reasons for it) but also developers who are not that strict in this regard and basic documentation skill can be sometimes just as important as the code itself (what prevents us from highlighting the fact that the Enum constants' internal states are actually mutable in the javadoc?).

splungebob
  • 5,357
  • 2
  • 22
  • 45
  • 2
    I find this large paragraph rather hard to follow; is it an answer, or a new question? Questions should not be posted as answers; [Stack Overflow is not a forum](https://meta.stackexchange.com/questions/92107). If it *is* an answer, would you please break it up into paragraphs to make it easier to read? – Tom Zych Aug 07 '18 at 21:44
  • 1
    It's an answer. I will break it up tommorow, yes, it was quite long, sorry about that. – Vítězslav Cibulka Aug 07 '18 at 21:55
0

I use a mutable enum for handling serialized numeric values outside of my control that I want to preserve when using and relaying. e.g.

VALUE_A = 1
VALUE_B = 13
VALUE_C = 17
VALUE_UNRECOGNIZED

e.g. What if I receive serialized value of 61? I don't recognize it, so I don't have an enum constant for it, I don't otherwise deal with it, but I don't want to fail it: I want to preserve the serialized value and relay it along.

Perhaps the canonical approach might be to create a new class with two fields: an immutable enum and the original value, but, IMHO, that seems more cumbersome.

danorton
  • 11,804
  • 7
  • 44
  • 52
-3

What I'd like to know is if there was any usecase to create mutable enums?

The enum constants are not themselves mutable, their fields are mutable.

Miserable Variable
  • 28,432
  • 15
  • 72
  • 133