Home

News: Creating Java Enum Objects at Runtime

  1. Creating Java Enum Objects at Runtime (20 messages)

    A Java enum type represents a fixed set of constants. Example: enum Day { SUN, MON, TUES, WED, THUR, FRI, SAT }What if you want to add one more day? Usually, you can't, and you may say: "why would I want to do that?". Well, let's say we just want to. If you are interested about my use case, see at the end. So let's try. First try, extend the enum: public enum DayPlus extends Day { MYDAY }This doesn't work, Javac doesn't like 'extends' here. The same if you try 'implements'. What about using reflection?Day.class.newInstance();This compiles - but doesn't work as either. After some more tries, I found the solution:Constructor con = Day.class.getDeclaredConstructors()[0]; Method[] methods = con.getClass().getDeclaredMethods(); for (Method m : methods) { if (m.getName().equals("acquireConstructorAccessor")) { m.setAccessible(true); m.invoke(con, new Object[0]); } } Field[] fields = con.getClass().getDeclaredFields(); Object ca = null; for (Field f : fields) { if (f.getName().equals("constructorAccessor")) { f.setAccessible(true); ca = f.get(con); } } Method m = ca.getClass().getMethod( "newInstance", new Class[] { Object[].class }); m.setAccessible(true); Day v = (Day) m.invoke(ca, new Object[] { new Object[] { "VACATION", Integer.MAX_VALUE } }); System.out.println(v.getClass() + ":" + v.name() + ":" + v.ordinal());I know it's a hack. The code does something the Java platform was supposed to disallow. But it works (at least with a Sun JDK). An now about the use case: I am implementing 'JaQu', which stands for Java Query and is something like LINQ for Java. If you don't know LINQ, it is a Microsoft invention and allows to write 'almost SQL' statements in C# applications, for example:var sundayWork = from t in timesheet where t.WeekDay == Day.SUN select t;This is C# code and may be translated to SQL:SELECT * FROM TIMESHEET T WHERE T.WEEKDAY='SUN'Now I like to do that in Java. The best I came up with is:Timesheet t = new Timesheet(); List sundayWork = db.from(t).where(t.weekDay).is(Day.SUN).select();For that to work I need a unique object in t.weekDay. If you want to know more about JaQu: it is part of the H2 Database Engine. You may also be interested in some example JaQu code.

    Threaded Messages (20)

  2. java Class updated from enum out. there are some methods used for handle enum class type. So enum reflection is not so painfull. Of couse, Class just an object, not a class hier. It's java's question.
  3. Groovy to the rescue[ Go to top ]

    You could also use the Groovy shell to evaluate new enums at runtime with something like new GroovyShell().evaluate("my enum code here"). I love one-liners like this :-)
  4. Security flaw?[ Go to top ]

    I'd say what you've done shows a security flaw in the JVM. Enums are supposed to be better than the old technique of passing special int values because you need not check for legal values. By extending the enum, you've shown it is possible to pass values into a method that it almost certainly cannot cope with.
  5. Re: Security flaw?[ Go to top ]

    I don't think that's going to work if you run with a security manager. setAccessible() requires the ReflectPermission("suppressAccessChecks") permission. If your security manager is null, then you can go hog wild, however.
  6. Re: Security flaw?[ Go to top ]

    I don't think it's a security flaw: it's easy to protect using a SecurityManager. Almost anything is possible when there is no SecurityManager. The designers of enum feature decided there is no use case to create new enum objects at runtime. They took great care to not allow it. Unfortunately I need this feature. It's an unexpected use case, and so the workaround is complicated. I hope in the future there will be an official way to create new enum objects (and a SecurityManager setting for it).
  7. Re: Security flaw?[ Go to top ]

    Unfortunately I need this feature.

    It's an unexpected use case
    I'm dying to hear what that use case is about. Regards, Slava Imeshev Cacheonix: Distributed Java Cache
  8. Re: Security flaw?[ Go to top ]

    I'm dying to hear what that use case is about.
    That is actually in the article. It is needed for JaQu, which is LINQ for Java.
  9. Re: Security flaw?[ Go to top ]

    The article starts with a simple statement that you want to add to enum just because. Slava
  10. Soooorry, I reviewed, I reply tooooooooooo quick. So I must admit, "you can be quick, but cannot be too quick":)
  11. You could try doing something like this: public static enum WeekDay implements Day { SUN, MON, Tues, WED, THUR, FRI, SAT; public int dayOfWeek() { return ordinal(); } } public static enum MyFavoriteDay implements Day { GoofingOff, WorkFromHome, Vacation; public int dayOfWeek() { return ordinal(); } }
  12. You could try doing something like this: public static enum WeekDay implements Day { ...
    Unfortunately you couldn't use switch/case any more. The following doesn't compile: Day d = WeekDay.SUN; switch(d) { case SUN: ... }
  13. There is a reason behind the fact that Java does not allow to extend an enum : Declaring an enum means : "Here is a new class, and the complete list of possible instances of this class are declared in the class". Using "complete", I mean there are no more, no less objects of this type. When inheriting from a class, you actually restrict the set of possible instances: as an example, think about Integer extends Number extends Object (in opposition, when inheriting from an interface, you actually extend the set of possible instances); XSD describes it better when defining a type based on an existing one: you can choose between and elements, where restriction can be seen as concrete (class) inheritance, and extension can be seen as interface inheritance. Now back to enum. Suppose we have the following enums: enum Day { SUN, MON, TUE, WED, THU, FRI, SAT } enum WorkingDay { MON, TUE, WED, THU, FRI } Now, what extends what ? 1. Day extends WorkingDay (add new constants (SAT, SUN) to WorkingDay): This means Day IS A WorkingDay, which is wrong, the following must raise a compile-time error: WorkingDay d = Day.SUN; 2. WorkingDay extends Day (remove constants (SAT, SUN) from Day): this might be acceptable regarding OO principles, but useless in common situation. Starting from an enum, the only way is to restrict the possible values. Adding new values to an existing enum means changing its parent hierarchy, which is usually not possible. Further, what would be the top-most enum class, containing all possible declared enum values ? 3. Day extends non-enum concrete class: the goal of an enum is to define a fixed set of immutable objects (instance fields should be declared final). This is not the case for the non-enum parent class: it can define its own instance variables + modifier methods. 4. non-enum class extends Day: the Day enum defines the complete set of instances. The goal of creating a plain class that extends an enum is to create instances of this class, which violates the enum principle.
  14. When inheriting from a class, you actually restrict the set of possible instances
    This sounds wrong to me. In most cases, when a class extends another, you add new fields, which extends the set of possible distinct instances.
  15. Why are you still using Java? Try Scala and your life will be simpler: abstract class Day extends Enumeration(0) { val SUN, MON, TUE, WED, THU, FRI, SAT = Value } object Day extends Day object DayPlus extends Day { val MYDAY = Value }
  16. Why are you still using Java?
    Because most people use Java. From Ohloh.org: Java 3,718 projects, C# 868, Scale 10. Java 1,910,517 commits, Scala 6,167. Most people use Java in their application. Mixing Java and another language (for example Scala or Groovy) in the same application is complicated. It would be required to split the code to access the database and the application code.
  17. Pointless and unnecessary[ Go to top ]

    What you should do is use a common interface for both the Day enum and the WeekDay enum and provide your own integer property. I have done this and it works brilliantly. e.g. interface Day { int value(); } public enum WeekDay implements IDay { SUN,MON,TUE,WED,THU,FRI,SAT; private Day() {} public int value() { return ordinal(); } // int to WeekDay helper. private final static WeekDay [] array = {SUN,MON,TUE,WED,THU,FRI,SAT}; public final static WeekDay get(int i) { return array[i]; } // IDay to WeekDay helper public final static WeekDay get(IDay day) { return WeekDay[day.value()]; } } public enum WorkingDay implements IDay { MON(1),TUE(2),WED(3),THU(4),FRI(5); private final int value; private WeekDay(int value) { this.value = value; } public int value() { return value; } } Look how damned easy that was!
  18. Re: Pointless and unnecessary[ Go to top ]

    In the use case I have (JaQu), the enum is defined by the user. That means the following code is fixed and can't be changed:
    enum Day { SUN, MON, TUES, WED, THUR, FRI, SAT }
    You have added an interface to this class. But it is not possible to add an interface to a class at runtime (after the class is loaded). So your solution can't be used for my tool.
  19. This is very good for creating the instance of an enum object but isn't this useless unless it gets added to the enum. If you were to call Day.values() and list all the Days you'd not see VACATION in the list. At least when I tried implementing this I didn't...
  20. For my use case this is not necessary. Is probably possible however using a similar trick. It's probably a bit more complicated because ENUM$VALUES is final.
  21. Example of use case[ Go to top ]

    I was trying to do the same thing, but did not find a way. Here's the use case since so many ppl are just saying there is no use case for this. ( :) if there is another way, I'm all hears). I want to compute matrices together. Those matrices have Sets of data as values. It's huge (billion/trillions or even more) and you have to do lots of comparisons so using an enumSet would be very nice. But then you need an enum Type, and since you don't know all the possible values of the set before you start the program (it comes from an input file), then you cannot use enumSet. The enumType would not be modified in any way, I just want to create it with the right data. Any ideas are welcome. Franck