是否可以根据输入文件创建Java枚举?
我正在使用Java 6。
假设我有一个文件availableFruits.txt
APPLE ORANGE BANANA
假设我想要一个包含availableFruits.txt
列出的值的枚举FruitType
,我能够这样做吗?
你不能在执行时填充枚举类型,不能 – 至少,不能没有像BCEL这样的东西,或者通过调用Java编译器。
当然,您可以编写代码来创建Java源文件,并在构建应用程序时构建它,如果之后不需要更改它。
否则,我只是创建一个包装类,它能够获取一组已知值并重用它们。 当然,您需要做的具体取决于您想要如何使用枚举。
那么Enum的意思是在编译时使用它。 如果您在编译时不知道您的Enum有什么值,那么它不是Enum它是一个集合。
如果你知道并且你只想根据文本文件中的值创建一个类文件,那么可以通过读取txt然后生成源代码来实现。
我希望通过编写自己的ClassLoader
子类,在字节数组中为枚举创建字节码,并使用defineClass
。 很难,也许,但可能。 我希望一旦你知道枚举的字节序列,从JVM规范中的信息自定义生成它并不困难。
现在,这是否是一个好主意……好吧,我怀疑只有极少数边缘情况。 (我想不出一个;我的意思是,创建它之后,你必须生成使用它的代码,对吗?)否则,你可能会更好地使用Map
或类似的东西。
不,除非您从文本文件生成枚举源文件。
正如其他人所说 – 不。 这是不可能的。 最好的方法是使用注册表模式。 读入值,将它们存储在某种可查询的映射中。 有点像Enum。
正如大家所指出的那样,这是不可能的。 但是,您可以创建一个地图 ,其中地图的关键字是您从文件中读取的值(APPLE,ORANGE,BANANA)和? 将是一个相关的值(例如int)。
当然,这样你基本上可以在没有类型安全的情况下实现相同的目标。
int i = fruitsMap.get("BANANA") // get the assoicated value
您可以使用动态生成的代码。 例如,使用编译器API。 我已经为该API编写了一个包装器,因此您可以在内存中编译类。 请参阅下面的代码。
你遇到的问题是它不是很有用,因为你不能使用这些值,除了在枚举编译后编译的类中。 你可以使用Enum.valueOf()等。但很多枚举的价值都会丢失。
正如其他人所建议的那样,使用Map会更简单并给出相同的好处。 如果你有一个库必须通过一个枚举,我只会使用枚举。 (或计划更多生成的代码)
public static Class generateEnum(String className, List 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()); }
我发现对文本生成代码很有用的一件事是你可以将它写入文件并在运行时调试它。 (该库支持此function)如果生成字节码,则更难调试。
该库名为Essence JCF。 (并且它不需要自定义类加载器)
你会如何用像JavaScript这样的动态语言来做到这一点:它只是带有一个值的字符串:“APPLE”,“ORANGE”,“BANANA”。
Java类型(类,接口,枚举)仅存在于编译器进行一些优化,类型检查,使重构成为可能等等。在运行时,您既不需要优化,也不需要类型检查,也不需要重构,所以正常的“字符串”是好吧,就像在JavaScript中一样,每个对象都是一个数字(Java中的Double),一个字符串(Java中的String)或一个复杂的对象(Java中的Map) – 即使在Java中,您也需要在运行时执行任何操作。