Why isn’t the hashcode of a java object consistent on different hosts

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 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.
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;
@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
  }
}
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

© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
better late than never.
只要开始,虽晚不迟
评论 抢沙发

请登录后发表评论

    暂无评论内容