10

I have an enum and it has a parameter (field) that is a String. Am I allowed to have a setter for this field?

public enum Blah {
    Monday("a"), Tuesday("b");
}

private final String letter;

Blah(String letter){
    this.letter = letter;
}

Am I allowed to do the following?

public String setLetter(String letter){
    this.letter = letter;
}
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
user2149780
  • 175
  • 2
  • 3
  • 13

6 Answers6

11

You need to remove the final modifier of the field in order for it to be settable:

public enum Blah {
    Monday("a"), Tuesday("b");


    private String letter;

    private Blah(String letter){
        this.letter = letter;
    }

    public void setLetter(String letter){
        this.letter = letter;
    }
}

http://ideone.com/QAZHol

Having mutable state in an enum is generally not recommended, however.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
5

Update: It's possible to have setters in enum types.

public class Main {

public enum Account {

    ACCOUNT("NAME");

    private String name;

    private Account(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public static void main(String[] args) {
    System.out.println(Account.ACCOUNT.getName()); // print NAME
    Account.ACCOUNT.setName("NEW");
    System.out.println(Account.ACCOUNT.getName()); // print NEW
}

}

Jan Hornych
  • 81
  • 1
  • 7
4

This doesn't work because the field is marked as final.

In principle, there is nothing preventing enums from having mutable fields. However, this is rarely if ever a good idea.

Taymon
  • 24,950
  • 9
  • 62
  • 84
  • 1
    And it is not a good idea because the value you set in the setter will be shared across all enum instances... – ACV Oct 26 '17 at 16:22
  • It's because there's only one instance per enum constant, so the value of the field is shared across all references to that instance. – Taymon Oct 27 '17 at 17:51
2

Allowed, but, if you are going to use the enum in multithreaded environment, please do not forget that although Java enum, effectively a lazy-initialized singleton, is guarded by Java during the lazy initialization (meaning here that no any other thread could access the enum until the initializing thread has not completed the initialization), it is not anyhow guarded against a concurrent use of the setter.

So, in the OP's case of simple setter it is enough to declare the mutable field as volatile (remove final of course):

volatile int letter;

In more complex cases like increments or others (highly unlikely with enums, but ... who knows, enum setter is itself an exotic thing) other concurrency weaponry like Atomics, synchronized blocks, Locks might be needed.

Also, there is a discussion on enum thread safety

igor.zh
  • 1,410
  • 15
  • 19
1

During using Enums it's always a good idea to declare variables as final.
Since it is not done in the above example we are able to set the value to something else.

By definition:
Enums are just like any other class, with a predefined NonChanging/FIXED set of instances.

Ahmed Nabil
  • 17,392
  • 11
  • 61
  • 88
Suhas
  • 3
  • 1
  • 11
0
public class EnumExample {
        public enum Blah {
        Monday("a"), Tuesday("b");


        private String letter;

        private Blah(String letter){
            this.letter = letter;
        }

        public void setLetter(String letter){
            this.letter = letter;
        }

        public String getLetter(){
             return letter;
        }
    }

        public static void main (String[] args)         {
             System.out.println("The Value of Monday is "+ Blah.Monday.getLetter());//prints a
             System.out.println("The Value of Tuesday is "+Blah.Tuesday.getLetter());//prints b
        }
}
Deepak
  • 2,094
  • 8
  • 35
  • 48