|
Sponsored Links
Resources
Enterprise Java Research Library
Get Java white papers, product information, case studies and webcasts
|
News
News
News
|
Messages: 20
Messages: 20
Messages: 20
Printer friendly
Printer friendly
Printer friendly
Post reply
Post reply
Post reply
XML
XML
XML
|
 |
Creating Java Enum Objects at Runtime
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<Timesheet> 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.
|
|
Message #265198
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Seems Class knowlege need updated
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.
|
|
Message #265202
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Groovy to the rescue
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 :-)
|
|
Message #265205
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Security flaw?
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.
|
|
Message #265209
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Security flaw?
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.
|
|
Message #265219
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Security flaw?
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).
|
|
Message #265242
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Creating Java Enum Objects at Runtime
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(); } }
|
|
Message #265253
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Creating Java Enum Objects at Runtime
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: ... }
|
|
Message #265451
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Security flaw?
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.
|
|
Message #265457
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Security flaw?
The article starts with a simple statement that you want to add to enum just because.
Slava
|
|
Message #265549
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Why inheriting from an enum does not make sense
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 <xsd:restriction> and <xsd:extension> 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.
|
|
Message #265568
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Why inheriting from an enum does not make sense
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.
|
|
Message #265598
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Creating Java Enum Objects at Runtime
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 }
|
|
Message #265675
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Creating Java Enum Objects at Runtime
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.
|
|
Message #266439
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Pointless and unnecessary
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!
|
|
Message #266608
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Pointless and unnecessary
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.
|
|
Message #267445
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
But how does this get added to the original enum?
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...
|
|
Message #267564
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: But how does this get added to the original enum?
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.
|
|
Message #307321
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Re: Seems Class knowlege need updated
Soooorry, I reviewed, I reply tooooooooooo quick. So I must admit, "you can be quick, but cannot be too quick":)
|
|
Message #309298
Post reply
Post reply
Post reply
Go to top
Go to top
Go to top
|
 |
Example of use case
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
|
|
 |
New content on TheServerSide.comNew content on TheServerSide.comNew content on TheServerSide.com |
 |
 |
Reza Rahman explores the features of the proposed JSR 299, Contexts and Dependency Injection for Java EE (CDI). When approved, it promises to be a key feature of Java EE 6.
(November 2, Article)
SAML is an XML-based standard for exchanging authentication and authorization data between security domains. The single most important problem that SAML was created to solve is the Web browser Single Sign-On problem. Many organizations are debating whether to stay with version 1.1 or move to 2.0. This article makes observations about both options.
(September 28, Article)
Joe Ottinger takes a look at how people learn, and applies it to the practice of programming. He notes that understanding how people learn is an essential part of working in a programming team.
(September 22, Article)
Stephen Maryka gave us an article about the Asynchronous Web and posed a number of questions that get examined like an approach to delivering Asynchronous Web capabilities through extensions to existing Java EE technologies.
(July 14, Article)
JavaServer Faces Flex goal is to provide users capability in creating standard Flex components, part of flexSDK which is open sourced through MPL license, as normal JSF components. This article by Ji Hoon Kim will provide an overview of creating a simple multilingual JSF page consisting of JSF Flex tags.
(June 29, Article)
In this session Jeff explores the key characteristics of successful SOA projects. He covers some of the patterns, and anti-patterns, tool sets, and strategies that he himself learned the hard way. Last, he provides a strategy and blueprint for achieving a high likelihood of success in your SOA project.
(June 23, Tech Talk)
Ari Zilka, CTO of Terracotta, Inc., talks about the new features in Terracotta 3.1, announced during JavaOne and available now.
(June 15, Tech Talk)
In this Tech Talk, Josh Long explores an integration challenge using Spring Integration and walks through the implementation, employing and expanding on the basic patterns of Enterprise Application Integration to tie together components into a function integration solution, and then demonstrates how Spring Integration helps address the integration requirements.
(June 15, Tech Talk)
In this Tech Talk, David Geary teaches you: The basics of Google Web Toolkit; How to implement Ajax-enabled applications in Java; Internationalization; Hooking into the browser history mechanism; Remote procedure calls.
(June 4, Tech Talk)
Jon Kern discusses the best architecture/technical solutions and ensure that they are repeated by all developers. By tackling the architecture up-front in a serial manner, subsequent parallel development will be much more manageable and predictable.
(May 28, Tech Talk)
This keynote describes the frustrations of modern knowledge workers in their quest to actually get some work done, and solutions for how to guard yourself against all those distractions. Neal Ford talks about environments, coding, acceleration, automation, and avoiding repetition as ways to defeat the misguided attempts to sap your ability to produce good work.
(May 26, Tech Talk)
Gil demonstrates how new, aggressive uses of already abundant compute capacity by common applications offer competitive value for application designers.
(May 21, Tech Talk)
Chris Keene introduces WaveMaker as a new way to automate the ability to generate Hibernate classes in order to more quickly bring OR mapping into an application.
(May 19, Article)
In this session Nati Shalom demonstrates how to take a standard Java EE web application and scale it out or down dynamically without changes to the application code. Seeing as most web applications are over-provisioned to meet infrequent peak loads, this is a dramatic change because it enables growing your application as needed, when needed, without paying for unutilized resources.
(May 19, Tech Talk)
Download the entire book of Jakarta-Struts Live and learn about Struts MVC, Tiles, the Validator, DynaActionForms, plug-ins, internationalization, and more.
(Book PDF Download)
The Application Server Matrix is a detailed listing of J2EE vendors and their application server products, with information on latest version numbers, J2EE spec support and licensing, pricing, platform support, and links to product downloads and reviews.
(Application Server Comparison Matrix)
|
|