9

Is there any way to add elements to a built in enum class in Java?

My question is similar to Can I add and remove elements of enumeration at runtime in Java, but that question seems to be geared towards constructing your own enum and then modifying it. I'm assuming there's an existing enum somewhere I can't change, something like

enum Days{ MONDAY, TUESDAY, WEDNESDAY }

and I want to add Thursday, Friday, etc. to it. So unfortunately, suggestions of how to use an interface to accomplish my goal, or other methods that would be more effective than enums, don't apply here.

As I understand it, enums are implicitly final, so I can't extend it and add more elements to it. It has private fields, but it appears I can use reflection to access those - could I change one of the private fields, even if I can't add a new one, i.e, change Monday to Thursday?

Edit: Clarification of Circumstances

People have suggested altering the code before it's compiled into the program. My code is part of a larger project that I can't change; the class with the enum in it is loaded by the larger program before my class gets access to it. At that point, I'd like to add the missing elements to the enum. Is bytecode manipulation still the way to go?

Community
  • 1
  • 1
en_Knight
  • 5,301
  • 2
  • 26
  • 46
  • 1
    I think you shouldn't do this, but if you really insist, [this blog post](http://www.jroller.com/VelkaVrana/entry/modify_enum_with_reflection) seems to be just what you want. – Vincent van der Weele Nov 23 '13 at 22:13
  • I don't fully understand? Let's assume i have the following code: Days firstDay = Days.MONDAY. What do you want to modify now? – isnot2bad Nov 23 '13 at 22:13

2 Answers2

7

Enums are intended to be static, final, immutable, instance-controlled objects that have the sense of constants. You should think of an enum any time your project contains a natural grouping or listing of things that are known at compile time.

The JVM guarantees that enums are instance-controlled and immutable at run-time. The binary compatibility of enums is also guaranteed so that if, later on, you add enum constants, your programs will continue to run.

The short answer is: "no, there is no easy way to extend an enum class in java."

One alternative is to have a base enum implement an interface that serves as the base type for the enum constants.

It is then possible to "extend" the enum by creating a new enum that implements the interface. Even so, this is not something that, by design, was ever intended to take place at run time.

scottb
  • 9,908
  • 3
  • 40
  • 56
  • That sounds like a good idea, but I can't change the base enum to make it implement an interface. I can't change the declaration of enum at all - it isn't mine. When you say "no, there is no easy way to ... " I have to wonder, is there a "hard" way to do it? – en_Knight Nov 23 '13 at 22:20
  • As Peter Lawrey has said, the "hard" way to do it is to change the class before it is loaded. It has to be this way because, again, JVM implementations are supposed to make strict guarantees about the inviolability of enums at run-time (i.e., they are secure). Is there a way to replace the deficient enum with a correct one that you've written yourself ... or even one that has been byte-code edited to become usable? – scottb Nov 23 '13 at 22:23
0

You can change a enum at runtime my altering the class at runtime before you load it. You can either compile an altered enum at runtime and load it or you can use byte code manipulation to alter it.

In short, include all the enums you need and you should never need to add to them at runtime. e.g. if there are only seven days in a weeks, include all of them at compile time.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • How do I use "byte code manipulation to alter it"? I would have included all 7 days, but I'm using an enum from somewhere I can't access or change that didn't include all 7 days (I don't know why) – en_Knight Nov 23 '13 at 22:17
  • either you can change it or your can't. If you can change it there are many ways to do this. If you can't change it I would like to know why not. The simplest solution is to de-compile the class or obtain the source, edit it and use your modified version instead. – Peter Lawrey Nov 23 '13 at 22:18