Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of Java enums

I was thinking about using enum type to manage i18n in a Java game I'm developing but I was curious about performance issues that can occur when working with enums that have lots of elements (thousands I think).

Actually I'm trying something like:

public enum Text {
  STRING1,
  STRING2,
  STRING3;

  public String text() {
    return text;
  }

  public String setText() {
    this.text = text;
  }
}

Then to load them I can just fill the fields:

static
{
  Text.STRING1.setText("My localized string1"); 
  Text.STRING2.setText("My localized string2"); 
  Text.STRING3.setText("My localized string3"); 
}

Of course when I'll have to manage many languages I'll load them from a file.

What I'm asking is

  • is an obect allocated (in addition to the string) for every element? (I guess yes, since enums are implemented with objects)
  • how is the right element retrieved from the enum? is it static at compile time? (I mean when somewhere I use Text.STRING1.text()). So it should be constant complexity or maybe they are just replaced during the compiling phase..
  • in general, is it a good approach or should I look forward something else?

Thanks

like image 647
Jack Avatar asked Dec 20 '10 14:12

Jack


4 Answers

Found and adapted a nice mix of enums and ResourceBundle:

public enum Text {
  YELL, SWEAR, BEG, GREET /* and more */ ;

  /** Resources for the default locale */
  private static final ResourceBundle res =
    ResourceBundle.getBundle("com.example.Messages");

  /** @return the locale-dependent message */
  public String toString() {
    return res.getString(name() + ".string");
  }
}

# File com/example/Messages.properties
# default language (english) resources
YELL.string=HEY!
SWEAR.string=§$%&
BEG.string=Pleeeeeease!
GREET.string=Hello player!

# File com/example/Messages_de.properties
# german language resources
YELL.string=HEY!
SWEAR.string=%&$§
BEG.string=Biiiiiitte!
GREET.string=Hallo Spieler!
like image 128
Andreas Dolk Avatar answered Nov 18 '22 09:11

Andreas Dolk


You're probably better off using the java.util.ResourceBundle class. It is designed to solve exactly this problem.

To answer your questions:

  1. Yes, there is exactly one instance of each enum value.
  2. Yes, constant complexity for looking up an Enum value.
  3. Not really. Changing the content/behaviour of the enum kinda defeats the purpose of having enums in the first place. They're supposed to represent fixed-range constants with type safety. You can do this kind of thing but that's not what they were designed for.
like image 39
Cameron Skinner Avatar answered Nov 18 '22 10:11

Cameron Skinner


I hate to hijack to topic, but relying on enums for i18n is going to eventually paint you into a corner. Java has proper i18n support, even going so far as to have a tutorial for it.

like image 7
Powerlord Avatar answered Nov 18 '22 10:11

Powerlord


although java has i18n support using ResourceBundle I do not think that idea to use enum for this purpose is so bad. I believe that these 2 approaches can be merged. You can create enum Texts that contains all your text identifiers. You can create resource bundles for each supported language and use the same identifiers in this bundle.

Then implement getText() method in the enum as following:

return ResourceBundle.getBundle("texts").getString(name());

So, you do not have to care about the initialization of texts for each language. The standard mechanism cares about this.

Now you use in code the enums and enjoy all features of bundles. You can also create unit test that verifies that all enum members have appropriate lines in bundle and vice versa to avoid garbage in your bundles.

I will probably use this approach in my next project. Thank you for the idea!

like image 2
AlexR Avatar answered Nov 18 '22 10:11

AlexR