Background
Recently, one of our API customers complains that the etag of our API is not working correctly. So, I started checking what’s wrong. And what I found was that the etag across different hosts is not consistent. So, the etag is a hex string of java object hashcode. In the beginning, I had no idea what’s wrong. Since the other APIs are working, only one of the API is not. So, I wrote a simple test code that prints each field on the object. Finally, I found the hashcode of java enum is different on different hosts. So why?
Why?
I just googled the question and found this post. It is exactly the same issue as I had.
Let’s take a look java enum hashcode definition in the official document.
public final int hashCode()Returns a hash code for this enum constant.Overrides:hashCode in class ObjectReturns:a hash code for this enum constant.public final int hashCode() Returns a hash code for this enum constant. Overrides: hashCode in class Object Returns: a hash code for this enum constant.public final int hashCode() Returns a hash code for this enum constant. Overrides: hashCode in class Object Returns: a hash code for this enum constant.
Enter fullscreen mode Exit fullscreen mode
See, what the problem is? Here, it says that it returns a hashcode for this enum constant. Enum constant is an object of the enum, and it is constant. So, it is consistent on the JVM. But, each JVM should have its own constant of the enum. That explains my question at the beginning. Enum’s on different JVMs will have different hash codes.
How to resolve the issue?
So, we know what is going on. But, how to resolve it. As you can see, the enum hashcode function is a final
method. So, which means we can’t override it.
This tells us that the only way to override the hashcode is the place where we use the enum object. Let’s an example.
class TestDAO {private String test1;private Type type;enum Type {APPLE,ORANGE}}class TestDAO { private String test1; private Type type; enum Type { APPLE, ORANGE } }class TestDAO { private String test1; private Type type; enum Type { APPLE, ORANGE } }
Enter fullscreen mode Exit fullscreen mode
Let’s override the hashcode method on TestDAO.
class TestDAO {private String id;private Type type;@Overridepublic hashCode(){Objects.hashCode(id, type.name());}@Overridepublic equals(){...}enum Type {APPLE,ORANGE}}class TestDAO { private String id; private Type type; @Override public hashCode(){ Objects.hashCode(id, type.name()); } @Override public equals(){ ... } enum Type { APPLE, ORANGE } }class TestDAO { private String id; private Type type; @Override public hashCode(){ Objects.hashCode(id, type.name()); } @Override public equals(){ ... } enum Type { APPLE, ORANGE } }
Enter fullscreen mode Exit fullscreen mode
Note, the difference is that we use type.name()
instead of the type itself. That resolves the issue. Not perfectly, but, works.
Reference:
https://madhead.me/posts/enums-fuckup/
https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#hashCode()
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag
原文链接:Why isn’t the hashcode of a java object consistent on different hosts
暂无评论内容