-1

Let us assume that I have to handle several constant strings that are closely related, for example types of messages ("ID1", "ID2", "ID3"). Currently I use a final class that only has public static final definitions:

public final class MessageType {
   public static final String ID1 = "ID1";
   public static final String ID2 = "ID2";
   public static final String ID3 = "ID3";
}

In the various classes I access the strings as MessageType.ID<X>. Is this the best way to handle this scenario or the best practice is different? Thanks.

molfo
  • 75
  • 7

1 Answers1

2

This approach has one big drawback: There's no decent way to transform a String such as "ID1" back to MessageType.ID1.

The common approach here is to use an enum:

public enum MessageType {
  ID1,
  ID2,
  ID3
}

Their String representation is MessageType.ID1.name(). You can transform the name back to a constant by iterating over MessageType.values().

This has the limitation that the constants need to be valid regarding the java syntax. Enums are basically a list of instances of that enum class. Writing down the constant names is essentially a call to a constructor. That means you can assign values to each instance:

public enum MessageType {
  ID1("ID 1"), //calls the constructor
  ID2("something else with spaces");

  private final String text; //field

  MessageType(String t) { //the constructor
    this.text = t;
  }

  //and the lookup:
  static MessageType getByText(String text) {
    for(MessageType t:values()) {
      if(t.text.equals(text)) {
        return t;
      }
    }
    return null;
  }

  public String getText() {
    return text;
  }
}

You can now access these longer Strings using MessageType.ID2.text. Calling MessageType.getByText("ID 1") will return MessageType.ID1.

f1sh
  • 11,489
  • 3
  • 25
  • 51
  • Thanks for the reply. The example is not very relevant, but what if I have to store strings with spaces or special characters? – molfo Aug 01 '22 at 10:52
  • Note that instance fields in enum types (like the `text` field) are not implicitly `final`. That means that with your sample code someone could write `MessageType.ID1.text = "Hello World";`. Please always make your instance fields in enum types final like this: `public final String text;` – Thomas Kläger Aug 01 '22 at 11:41
  • @ThomasKläger agreed, edited the code. I used a non-final public field for simplicity, changed it to a private final field with a getter. – f1sh Aug 01 '22 at 12:26