English 中文(简体)
What s the limit to the number of members you can have in a java enum?
原标题:

Assuming you have a hypothetical enum in java like this (purely for demonstration purposes, this isn t code i m seriously expecting to use):

enum Example{
    FIRST,
    SECOND,
    THIRD,
    ...
    LAST;
}

What s the maximum number of members you could have inside that enum before the compiler stops you?

Secondly, is there any performance difference at runtime when your code is referencing an enum with say, 10 members as opposed to 100 or 1,000 (other than just the obvious memory overhead required to store the large class)?

最佳回答

The best way to find out the answer to this type of question is to try it. Start with a little Python script to generate the Java files:

n = input()
print "class A{public static void main(String[] a){}enum B{"
print  , .join("C%d" % x for x in range(n))
print  }} 

Now try with 1,10,100,1000... works fine, then BAM:

A.java:2: code too large C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15,C16,C17,C18,C19,C20,C21,C22,...

Seems like I hit some sort of internal limit. Not sure if it s a documented limit, if it s dependent on the specific version of my compiler, or if its some system dependant limit. But for me the limit was around 3000 and appears to be related to the source code size. Maybe you could write your own compiler to bypass this limit.

问题回答

The language specification itself doesn t have a limit. Yet, there are many limitations that classfile has that bound the number of enums, with the upper bound being aruond 65,536 (2^16) enums:

Number of Fields The JVMS 4.1 specifies that ClassFile may have up to 65,536 (2^16) fields. Enums get stored in the classfile as static field, so the maximum number of enum values and enum member fields is 65,536.

Constant Pool The JVMS also specifies that the Constant Pool may have up to 65,536. Constant Pools store all String literals, type literals, supertype, super interfaces types, method signatures, method names, AND enum value names. So there must be fewer than 2^16 enum values, since the names strings need to share that Constant Pool limit.

Static Method Initialization The maximum limit for a method is 65,535 bytes (in bytecode). So the static initializer for the Enum has to be smaller than 64Kb. While the compiler may split it into different methods (Look at Bug ID: 4262078) to distribute the initializations into small blocks, the compiler doesn t do that currently.

Long story short, there is no easy answer, and the answer depends not only on the number of enum values there are, but also the number of methods, interfaces, and fields the enums have!

The maximum number of enum values will I think be just under the 65536 maximum number of fields/constant pool entries in the class. (As I mentioned in a comment above, the actual values shouldn t take up constant pool entries: they can be "inlined" into the bytecode, but the names will.)

As far as the second question is concerned, there s no direct performance difference, but it s conceivable that there ll be small indirect performance differences, partly because of the class file size as you say. Another thing to bear in mind is that when you use enum collections, there are optimised versions of some of the classes for when all of the enum values fit within a certain range (a byte, as I recall). So yes, there could be a small difference. I woudln t get paranoid, though.

This is an extension of the comments to the original question.

There are multiple problems with having a LOT of enums.

The main reason is that when you have a lot of data it tends to change, or if not you often want to add new items. There are exemptions to this like unit conversions that would never change, but for the most part you want to read data like this from a file into a collection of classes rather than an enum.

To add new items is problematic because since it s an enum, you need to physically modify your code unless you are ALWAYS using the enums as a collection, and if you are ALWAYS using them as a collection, why make them enums at all?

The case where your data doesn t change--like "conversion units" where you are converting feet, inches, etc. You COULD do this as enums and there WOULD be a lot of them, but by coding them as enums you lose the ability to have data drive your program. For instance, a user could select from a pull-down list populated by your "Units", but again, this is not an "ENUM" usage, it s using it as a collection.

The other problem will be repetition around the references to your enum. You will almost certainly have something very repetitive like:

if(userSelectedCard() == cards.HEARTS)
    graphic=loadFile("Heart.jpg");
if(userSelectedCard() == cards.SPADES)
    graphic=loadFile("Spade.jpg");

Which is just wrong (If you can squint to where you can t read the letters and see this kind of pattern in your code, you KNOW you are doing it wrong).

If the cards were stored in a card collection, it would be easier to just use:

graphic=cards.getGraphicFor(userSelectedCard());

I m not saying that this can t be done with an enum as well, but I am saying that I can t see how you would use these as enums without having some nasty code-block like the one I posted above.

I m also not saying that there aren t cases for enums--there are lots of them, but when you get more than a few (7 was a good number), you re probably better off with some other structure.

I guess the exception is when you are modeling real-world stuff that has that many types and each must be addressed with different code, but even then you are probably better off using a data file to bind a name to some code to run and storing them in a hash so you can invoke them with code like: hash.get(nameString).executeCode(). This way, again, your "nameString" is data and not hard-coded, allowing refactoring elsewhere.

If you get in the habit of brutally factoring your code like this, you can reduce many programs by 50% or more in size.





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签