Ste*_*nZL 2 java enums hashcode
我现在只知道Java中没有Enum的hashCode()实现。它返回的只是 super.hashCode(),而其他不可变类(例如 String)都有自己的 hashCode() 实现。这使得 Enum 在不同 JVM 中使用时不安全。我认为ordinal()非常适合计算Enum的hashCode(),但是Enum中的hashCode()被定义为final,我无法覆盖它。我能想到的唯一解决方案是创建一个类似于 Enum 的全新类。有什么建议吗?
我想实现这样的目标:
enum Fruit {
APPLE, POMEGRANATE, KIWI;
@override
public int hashCode() {
return Objects.hash(super.ordinal());
}
@override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
}
Fruit other = (Fruit)obj;
return super.ordinal() == other.ordinal();
}
}
Run Code Online (Sandbox Code Playgroud)
有什么解决办法吗?或者我想了解为什么这个解决方案不好,因此在java中不允许。
你说:
\n\n\n这使得 Enum 在不同 JVM 中使用时不安全。
\n
正如shmosel 所评论的那样,您永远不能依赖hashCode任何对象在 JVM 之间保持一致。
所承诺的合同Object##hashCode明确指出,您不能依赖hashCodeJVM 的调用之间的相同性。引用Javadoc:
\n\n从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。
\n
你说:
\n\n\n我认为 ordinal() 非常适合计算 Enum 的 hashCode()
\n
不,我想不是。您可以定义应用程序版本之间枚举元素的顺序。您甚至可以添加或删除元素。因此,我们通常不应该依赖应用程序版本之间的序号。
\n你说:
\n\n\n我能想到的唯一解决方案是创建一个类似于 Enum 的全新类。
\n
我相信你会遇到麻烦。
\n你说:
\n\n\n有什么建议吗?
\n
是的。指定一个键。
\n如果您想标识由 subclass\xe2\x80\x99 对象表示的实体的值Enum,我建议您向枚举类添加一个成员字段以唯一标识每个实例。
您分配的值取决于您的问题域。在特定行业或公司中,可能存在已知的标识符。例如,在处理水果时,也许可以指定一个拉丁科学植物学名称。
\n在关系数据库理论中,这个名称是自然键。
\nenum Fruit {\n APPLE ( "Malus domestica" ) , \n POMEGRANATE ( "Punica granatum" ) , \n KIWI ( "Actinidia deliciosa" );\n \n final String botanicalName ;\n \n Fruit ( String botanicalName ) \n {\n this.botanicalName = botanicalName ;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n用法:
\nfor( Fruit fruit : Fruit.values() )\n{\n System.out.println( fruit + " = " + fruit.botanicalName ) ;\n}\nRun Code Online (Sandbox Code Playgroud)\n运行时。
\nAPPLE = Malus domestica\nPOMEGRANATE = Punica granatum\nKIWI = Actinidia deliciosa\nRun Code Online (Sandbox Code Playgroud)\n\n如果您的业务域中不存在此类标识符,则分配任意永久标识符。
\n如果您不知道,请使用通用唯一标识符 (UUID)。看UUID班级。
在关系数据库理论中,我们称之为代理键。
\nenum Fruit {\n APPLE ( UUID.fromString( "9307e05e-b337-41e8-acec-a00645b00878" ) ) , \n POMEGRANATE ( UUID.fromString( "6f67df08-b400-49af-94ed-e068ee58412f" ) ) , \n KIWI ( UUID.fromString( "028c9e8a-9d25-48a1-b150-b892ea26807f" ) ) ;\n \n final UUID id ;\n \n Fruit ( UUID id ) \n {\n this.id = id ;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n用法:
\nfor( Fruit fruit : Fruit.values() )\n{\n System.out.println( fruit + " \xe2\x9e\x94 " + fruit.id ) ;\n}\nRun Code Online (Sandbox Code Playgroud)\n运行时。
\nAPPLE \xe2\x9e\x94 9307e05e-b337-41e8-acec-a00645b00878\nPOMEGRANATE \xe2\x9e\x94 6f67df08-b400-49af-94ed-e068ee58412f\nKIWI \xe2\x9e\x94 028c9e8a-9d25-48a1-b150-b892ea26807f\nRun Code Online (Sandbox Code Playgroud)\n顺便说一句,从技术上来说,说 \xe2\x80\x9c 没有实现 \xe2\x80\x9d 是不正确hashCode()的Enum。继承的实现就是它的实现。这种观点是OOP的基础。
| 归档时间: |
|
| 查看次数: |
160 次 |
| 最近记录: |