如何获取覆盖hashCode()的对象的唯一ID?

iva*_*off 224 java identity hashcode

当Java中的类不覆盖hashCode()时,打印此类的实例会给出一个很好的唯一编号.

对象的Javadoc说关于hashCode():

尽可能合理,Object类定义的hashCode方法确实为不同的对象返回不同的整数.

但是当类重写hashCode()时,我怎样才能获得它的唯一编号?

Bri*_*new 335

System.identityHashCode(yourObject)yourObject的"原始"哈希码作为整数给出.唯一性不一定得到保证.Sun JVM实现将为您提供与此对象的原始内存地址相关的值,但这是一个实现细节,您不应该依赖它.

编辑:答案修改后汤姆的评论下面重新.内存地址和移动对象.

  • 对于实际的JVM实现,完全不保证**的唯一性.保证唯一性要求GC不需要重定位/压缩,或者需要大而昂贵的数据结构来管理活动对象的哈希码值. (12认同)
  • Brian:这不是实际的内存位置,您在第一次计算时碰巧得到了地址的重新版本.在现代VM中,对象将在内存中移动. (11认同)
  • 无论有多少个对象,或者有多少内存.hashCode()和identityHashCode()都不需要生成唯一编号. (9认同)
  • System.identityHashCode在HotSpot中不是唯一的,很难学到它. (5认同)
  • 因此,如果在内存地址0x2000上创建了一个对象,然后由VM移动了该对象,那么在0x2000上创建了另一个对象,它们是否具有相同的`System.identityHashCode()`? (2认同)

Val*_*her 28

Object的javadoc指定了

这通常通过将对象的内部地址转换为整数来实现,但JavaTM编程语言不需要此实现技术.

如果一个类重写了hashCode,则意味着它想要生成一个特定的id,这将(人们可以希望)具有正确的行为.

您可以使用System.identityHashCode获取任何类的id.


Joh*_*ang 8

也许这个快速,肮脏的解决方案可行?

public class A {
    static int UNIQUE_ID = 0;
    int uid = ++UNIQUE_ID;

    public int hashCode() {
        return uid;
    }
}
Run Code Online (Sandbox Code Playgroud)

这也给出了正在初始化的类的实例数.

  • 假设您有权访问该类的源代码 (3认同)
  • 它并不总是有效。这堂课可能是最后一堂课。我认为“System.identityHashCode”是一个更好的解决方案 (2认同)
  • 对于线程安全,可以使用"AtomicLong",如[this answer](http://stackoverflow.com/a/8939049/1143274). (2认同)

ovu*_*tin 7

hashCode()方法不是为对象提供唯一标识符.它宁可将对象的状态(即成员字段的值)消化为单个整数.该值主要由一些基于散列的数据结构(如地图和集合)使用,以有效地存储和检索对象.

如果您需要对象的标识符,我建议您添加自己的方法而不是覆盖hashCode.为此,您可以创建如下所示的基本接口(或抽象类).

public interface IdentifiedObject<I> {
    I getId();
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

public class User implements IdentifiedObject<Integer> {
    private Integer studentId;

    public User(Integer studentId) {
        this.studentId = studentId;
    }

    @Override
    public Integer getId() {
        return studentId;
    }
}
Run Code Online (Sandbox Code Playgroud)

对于id生成,您可以查看我的博客帖子,我试图解释一些生成唯一ID的方法.


Fra*_*kie 7

// looking for that last hex?
org.joda.DateTime@57110da6
Run Code Online (Sandbox Code Playgroud)

hashcode如果您在对对象执行 a 操作时正在研究Java 类型.toString(),则底层代码如下:

Integer.toHexString(hashCode())
Run Code Online (Sandbox Code Playgroud)


How*_*ope 5

我想出了这个解决方案,该解决方案适用于我在多个线程上创建对象并且可序列化的情况:

public abstract class ObjBase implements Serializable
    private static final long serialVersionUID = 1L;
    private static final AtomicLong atomicRefId = new AtomicLong();

    // transient field is not serialized
    private transient long refId;

    // default constructor will be called on base class even during deserialization
    public ObjBase() {
       refId = atomicRefId.incrementAndGet()
    }

    public long getRefId() {
        return refId;
    }
}
Run Code Online (Sandbox Code Playgroud)