Is it possible to create Java enums based on input file?
I'm using Java 6.
Suppose I have a file availableFruits.txt
APPLE
ORANGE
BANANA
Suppose I want an enum FruitType
that contains values lis开发者_StackOverflowted in availableFruits.txt
, will I be able to do this?
You can't populate an enum type at execution time, no - at least, not without something like BCEL, or by calling the Java compiler.
You can write code to create a Java source file, of course, and build that when you build your app, if you don't need it to be changed afterwards.
Otherwise, I'd just create a wrapper class which is able to take a set of known values and reuse them. Exactly what you need to do will depend on how you wanted to use the enum, of course.
Well the point of an Enum is to use it at compile time. If you don't know at compile time what values your Enum has then it's not an Enum it's a collection.
If you do know and you just want to create a class file base on the values in the text file then yes it's possible by reading the txt then generating the source code.
I expect it's possible, by writing your own ClassLoader
subclass, creating the bytecode for the enum in a byte array, and using defineClass
. Hard, maybe, but possible. I expect once you know the byte sequence for an enum, it's not that hard to custom-generate it from the info in the JVM spec.
Now, whether it's a good idea...well, I suspect only in a very small number of edge cases. (I can't think of one; I mean, having created it, you'd have to generate code to use it, right?) Otherwise, you're probably better off with a Map
or similar.
No, not unless you generate the enum source file from the text file.
As everyone else said- no. It's not possible. Your best shot is to use the Registry pattern. Read in the values, store them in some sort of query-able map. Sort of like an Enum.
As everyone pointed out, it's not possible. However, you could create a Map where the key of your map would be the value you read from you file (APPLE,ORANGE,BANANA) and the ? would be an associated valu (int for example).
This way you could basically achieve the same goal without the type safety, of course.
int i = fruitsMap.get("BANANA") // get the assoicated value
You can with dynamically generated code. e.g. Using the Compiler API. I have written a wrapper for that API so you can compile classes in memory. See the code below.
The problem you have is that its not very useful as you cannot use these values except in classes which were compiled AFTER your enum was compiled. You can use Enum.valueOf() etc. But a lot of the value of enums is lost.
As other have suggested, using a Map would be simpler and give the same benefit. I would only use the enum if you have a library has to be passed an Enum. (Or plan more generated code)
public static Class generateEnum(String className, List<String> enums) {
StringBuilder code = new StringBuilder();
code.append("package enums; public enum enums." + className + " {\n");
for (String s : enums)
code.append("\t"+s+",\n");
code.append("}");
return CompilerUtils.CACHED_COMPILER
.loadFromJava("enums."+className, code.toString());
}
One of things I find useful with text generated code is that you can write it to a file and debug it even at run time. (The library supports this) If you byte code generation, its harder to debug.
The library is called Essence JCF. (And it doesn't require a custom class loader)
How would you do this in a dynamic language like JavaScript: it would be just string with one of values: "APPLE", "ORANGE", "BANANA".
Java types (classes, interfaces, enums) exist only for compiler to do some optimizations, and type checking, to make refactoring possible, etc. At runtime you don't need neither optimizations, type checking nor refactoring, so normal "string" is OK, just like in JavaScript every object is either a number (Double in Java), a string (String in Java) or a complex object (Map in Java) - that's all you need to do anything at runtime even in Java.
精彩评论