方便地在 enum 和 int / String 之间映射
当使用只能取有限数量值的变量/参数时,我尝试始终使用 Java 的 enum
,就像“
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
只要我留在代码中,就可以正常工作”。但是,出于相同目的,我经常需要与使用普通 int
(或 String
)值的其他代码进行交互,或者我需要从数据库读取/写入数据库其中数据存储为数字或字符串。
在这种情况下,我希望有一种方便的方法将每个枚举值与一个整数关联起来,这样我就可以转换两种方式(换句话说,我需要一个“可逆枚举”)。
从 enum 到 int 很容易:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
然后我可以通过 BonusType x = MONTHLY; 访问 int 值。 int id = x.id;
。
然而,我看不出有什么好的相反的方法,即从 int 到 enum。理想情况下,
BonusType bt = BonusType.getById(2);
我能想到的唯一解决方案是:
- 将查找方法放入枚举中,该方法使用
BonusType.values()
填充映射“int -> enum”,然后缓存并将其用于查找。可以,但我必须将此方法完全相同地复制到我使用的每个枚举中:-(。 - 将查找方法放入静态实用程序类中。然后我只需要一个“查找”方法,但我必须摆弄反射以使其适用于任意枚举。
一个简单的(?)问题,这两种方法似乎都非常尴尬。
对于这样
When working with variables/parameters that can only take a finite number of values, I try to always use Java's enum
, as in
public enum BonusType {
MONTHLY, YEARLY, ONE_OFF
}
As long as I stay inside my code, that works fine. However, I often need to interface with other code that uses plain int
(or String
) values for the same purpose, or I need to read/write from/to a database where the data is stored as a number or string.
In that case, I'd like to have a convenient way to associate each enum value with a an integer, such that I can convert both ways (in other words, I need a "reversible enum").
Going from enum to int is easy:
public enum BonusType {
public final int id;
BonusType(int id) {
this.id = id;
}
MONTHLY(1), YEARLY(2), ONE_OFF(3);
}
Then I can access the int value as BonusType x = MONTHLY; int id = x.id;
.
However, I can see no nice way for the reverse, i.e. going from int to enum. Ideally, something like
BonusType bt = BonusType.getById(2);
The only solutions I could come up with are:
- Put a lookup method into the enum, which uses
BonusType.values()
to fill a map "int -> enum", then caches that and uses it for lookups. Would work, but I'd have to copy this method identically into each enum I use :-(. - Put the lookup method into a static utility class. Then I'd only need one "lookup" method, but I'd have to fiddle with reflection to get it to work for an arbitrary enum.
Both methods seem terribly awkward for such a simple (?) problem.
Any other ideas/insights?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
enum → int
int → enum
String → enum
enum → String
旁注:
正如您正确指出的那样,
ordinal()
在不同版本之间可能“不稳定”。这就是为什么我总是将常量作为字符串存储在数据库中的确切原因。 (实际上,当使用 MySql 时,我将它们存储为 MySql 枚举!)enum → int
int → enum
String → enum
enum → String
A side-note:
As you correctly point out, the
ordinal()
may be "unstable" from version to version. This is the exact reason why I always store constants as strings in my databases. (Actually, when using MySql, I store them as MySql enums!)http://www.javaspecialists.co.za/archive/Issue113.html
该解决方案一开始与您的解决方案类似,将 int 值作为枚举定义的一部分。然后,他继续创建一个基于泛型的查找实用程序:
这个解决方案很好,不需要“摆弄反射”,因为它基于所有枚举类型隐式继承 Enum 接口的事实。
http://www.javaspecialists.co.za/archive/Issue113.html
The solution starts out similar to yours with an int value as part of the enum definition. He then goes on to create a generics-based lookup utility:
This solution is nice and doesn't require 'fiddling with reflection' because it's based on the fact that all enum types implicitly inherit the Enum interface.
我在网上找到了这个,它非常有帮助并且易于实现。
这个解决方案不是我做的
http://www.ajaxonomy .com/2007/java/making-the-most-of-java-50-enum-tricks
}
I found this on the web, it was very helpful and simple to implement.
This solution was NOT made by me
http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks
}
似乎这个问题的答案随着 Java 8 的发布而过时了。
JVM比如数据库。
与关键值。
Seems the answer(s) to this question are outdated with the release of Java 8.
JVM such as a database.
with the key values.
org.apache.commons.lang.enums.ValuedEnum;
为了节省我为每个 Enum 编写大量样板代码或重复代码的工作,我使用了 Apache Commons Lang 的
ValuedEnum
。定义:
用法:
int ->值枚举:
org.apache.commons.lang.enums.ValuedEnum;
To save me writing loads of boilerplate code or duplicating code for each Enum, I used Apache Commons Lang's
ValuedEnum
instead.Definition:
Usage:
int -> ValuedEnum:
您也许可以使用类似的东西
,这会减少实用程序类中反射的需要。
You could perhaps use something like
That would reduce the need for reflection in your utility class.
步骤 1
定义一个
接口
EnumConverter第2步
创建一个类名ReverseEnumMap
第3步
转到您的
Enum
类和使用
它,当然还要重写接口方法。您还需要初始化一个静态 ReverseEnumMap。EnumConverter
实现第 4 步
现在创建一个
Communication
类文件并调用它的新方法将Enum
转换为String
和字符串
到枚举
。我刚刚出于解释目的放置了 main 方法。点击查看完整说明
Step 1
Define an
interface
EnumConverterStep 2
Create a class name ReverseEnumMap
Step 3
Go to you
Enum
class andimplement
it withEnumConverter<ContentType>
and of course override interface methods. You also need to initialize a static ReverseEnumMap.Step 4
Now create a
Communication
class file and call it's new method to convert anEnum
toString
andString
toEnum
. I have just put main method for explanation purpose.Click for for complete explanation
在这段代码中,为了永久和密集的搜索,有内存或进程可供使用,我选择内存,以转换器数组作为索引。
我希望它有帮助
In this code, for permanent and intense search , have memory or process for use, and I select memory, with converter array as index.
I hope it's helpful
使用界面来显示谁是老大。
结果:
Use an interface to show it who's boss.
And the result:
.ordinal()
和values()[i]
都不稳定,因为它们依赖于枚举的顺序。因此,如果您更改枚举的顺序或添加/删除一些枚举,您的程序将会中断。这是在 enum 和 int 之间进行映射的简单而有效的方法。
将其应用于字符串应该不难。
Both the
.ordinal()
andvalues()[i]
are unstable since they are dependent to the order of enums. Thus if you change the order of enums or add/delete some your program would break.Here is a simple yet effective method to map between enum and int.
Applying it for strings shouldn't be difficult.
我不确定 Java 中是否相同,但 C 中的枚举类型也会自动映射到整数,因此您可以使用类型或整数来访问它。您是否尝试过简单地用整数访问它?
I'm not sure if it's the same in Java, but enum types in C are automatically mapped to integers as well so you can use either the type or integer to access it. Have you tried simply accessing it with integer yet?
非常好的问题:-)我不久前使用了类似于弗格森先生的解决方案。我们的反编译枚举如下所示:
看到这里,很明显为什么
ordinal()
不稳定。它是super(s, i);
中的i
。我也悲观地认为您可以想出比您已经列举的这些更优雅的解决方案。毕竟,枚举与任何最终类一样都是类。Really great question :-) I used solution similar to Mr.Ferguson`s sometime ago. Our decompiled enum looks like this:
Seeing this is apparent why
ordinal()
is unstable. It is thei
insuper(s, i);
. I'm also pessimistic that you can think of a more elegant solution than these you already enumerated. After all enums are classes as any final classes.为了完整起见,这里提供了一种通过索引从任何枚举类型检索枚举值的通用方法。我的目的是使该方法看起来像 Enum。 valueOf(类,字符串)。仅供参考,我从
指数相关问题(已在此处深入讨论)仍然适用。
For the sake of completeness, here is a generic approach to retrieve enum values by index from any enum type. My intention was to make the method look and feel like Enum.valueOf(Class, String). Fyi, i copied this method from here.
Index related issues (already discussed in depth here) still apply.
我需要一些不同的东西,因为我想使用通用方法。我正在从字节数组读取枚举。这就是我想出的地方:
枚举的示例:
}
I needed something different because I wanted to use a generic approach. I'm reading the enum to and from byte arrays. This is where I come up with:
Example of enum's:
}
只是因为接受的答案不是独立的:
支持代码:
使用示例:
Just because the accepted answer is not self contained:
Support code:
Example of use:
给出:
公共枚举 BonusType {
每月 (0)、每年 (1)、一次性 (2)
}
BonusType 奖金 = YEARLY;
System.out.println(bonus.Ordinal() + ":" + Bonus)
输出:
1:每年
given:
public enum BonusType {
MONTHLY(0), YEARLY(1), ONE_OFF(2)
}
BonusType bonus = YEARLY;
System.out.println(bonus.Ordinal() + ":" + bonus)
Output:
1:YEARLY
如果您有一个类 Car
并且属性 Color 是一个类
并且您想要将 Color 转换为枚举,
只需在 >Color 类在 ColorEnum 中转换 Color
并在 ColorEnum 中实现方法 getById()
现在您可以使用 classMap
If you have a class Car
And the property Color is a class
And you want to convert Color to an Enum
Simply add a method in Color class to convert Color in ColorEnum
and inside ColorEnum implements the method getById()
Now you can use a classMap