在Java中为枚举引入默认值的通用机制
在我们当前的项目中,我们正在将一些神奇的数字从数据库映射到java枚举,如下所示:在Java中为枚举引入默认值的通用机制,java,Java,在我们当前的项目中,我们正在将一些神奇的数字从数据库映射到java枚举,如下所示: public interface WithCode { Integer getCode(); } public enum Role implements WithCode { OWNER(1), ADMIN(2), USER(3); @Getter Integer code; Role(Integer code) { this.code =
public interface WithCode {
Integer getCode();
}
public enum Role implements WithCode {
OWNER(1),
ADMIN(2),
USER(3);
@Getter Integer code;
Role(Integer code) {
this.code = code;
}
}
我们有很多这样的方法,所以我们创建了一个实用程序,可以通过ID查找适当的枚举,如下所示:
public interface EnumLookuper {
static <T extends Enum<T> & WithCode> T ofCode(int code, Class<T> enumType) {
return Arrays.stream(enumType.getEnumConstants())
.filter(value -> Objects.equals(value.getCode(), code))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException(String.format("Unknown %s with code %d", enumType.getName(), code)));
}
}
用接口强制默认值实际上是行不通的,因为我们需要为每个枚举成员提供默认值。有没有为每个枚举引入优雅的回退/未知值的想法
编辑
使用自定义“未知值接口”将迫使我对每个枚举成员实现未知值,例如:
interface UnknownValueProvider<T> {
T unknown();
}
public enum Role implements WithCode, UnknownValueProvider<Role> {
OWNER(1) {
public Role unknown() {
return ...;
}
}
接口未知值提供程序{
T未知();
}
公共枚举角色使用代码实现,未知值提供程序{
业主(1){
公共角色未知(){
返回。。。;
}
}
(注意:我不熟悉您拥有的部分代码,即按ID获取枚举的第二个代码块的大部分。它似乎过于复杂/不直观,并且与我发现的执行类似功能的所有代码都不同,请参见。有什么原因使它像我丢失的那样?)
我以前遇到过类似的问题,但有一些细微的区别。在我的例子中,我使用
valueOf()
获取枚举,但我想使其不区分大小写。因此,在我的枚举中,我重载了(?)valueOf(anyCaseParam)
以返回valueOf(anyCaseParam.toUpperCase())
我的建议
您应该将UNKNOWN(-1)
添加到枚举列表中(这样您就有了一个要检索的枚举)
根据这个答案,我修改了最后一段代码,以符合您的要求:
public T getByID(int num) {
// Old code:
//return map.get(num);
int unknownEnum= -1;
if(map.get(num)!=null)
return map.get(num);
else
return map.get(unknownEnum);
}
如果您愿意,您甚至可以使用另一个抛出异常的方法,而不是返回
未知的值。您无法返回一些新的枚举值,除非您直接将其添加到枚举类中。可能返回null/Optional会有帮助我正在考虑使用Optional
,但我需要更改很多客户机代码在这种情况下,我看到的最佳解决方案是将此未知字段添加到每个枚举中(在过去可以预期它们的需要)。尝试破解enum是不值得的。抱歉,我可能还不够清楚。我指的是你从向前获取实例的角度所做的事情。如果你真的需要使用enum实例,或者你可以用一个公共接口替换它,比如说命令
。你的enum将使用code&Co同时实现mmand
并且您还有一个实现该接口的UnknownCommand
类。然后,您的lookuper将返回一个命令
,如果可以找到匹配项,它将是一个枚举实例,或者是一个未知实例,您的代码只需调用命令。execute()
。
public T getByID(int num) {
// Old code:
//return map.get(num);
int unknownEnum= -1;
if(map.get(num)!=null)
return map.get(num);
else
return map.get(unknownEnum);
}