当Java中的类不重写hashCode()时, 打印这个类的实例会得到一个很好的唯一编号。

Object的Javadoc说hashCode():

在合理实用的情况下,类Object定义的hashCode方法确实为不同的对象返回不同的整数。

但是当类重写hashCode()时,我如何获得 它唯一的数字?


当前回答

如果它是一个可以修改的类,则可以声明一个类变量static java.util.concurrent.atomic.AtomicInteger nextInstanceId。(你必须以明显的方式给它一个初始值。)然后声明一个实例变量int instanceId = nextInstanceId.getAndIncrement()。

其他回答

如果它是一个可以修改的类,则可以声明一个类变量static java.util.concurrent.atomic.AtomicInteger nextInstanceId。(你必须以明显的方式给它一个初始值。)然后声明一个实例变量int instanceId = nextInstanceId.getAndIncrement()。

也许这个快速,肮脏的解决方案会起作用?

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

    public int hashCode() {
        return uid;
    }
}

这也给出了被初始化的类的实例数。

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

编辑:回答修改以下汤姆的评论re.内存地址和移动对象。

由于Object.hashCode()和System.identityHashCode()不提供保证唯一的id,我认为正确的答案是生成一个UUID或GUID:

java.util.UUID.randomUUID()

这个答案是线程安全的,并且可以跨不同的虚拟机工作。

例如,可识别类可以被扩展为提供任何具有唯一ID的类:

public abstract class Identifiable {
    public final UUID id = UUID.randomUUID();
}

...

public class Example extends Identifiable {}

...

public static void main(String[] args) {

    Example example1 = new Example();
    Example example2 = new Example();

    example1.id.toString(); // e.g. 8308798d-7cec-427d-b7f8-7be762f3b5c7
    example1.id.equals(example1.id); // true
    example1.id.equals(example2.id); // false
}

我想出了这个解决方案,在我的情况下,我有对象创建在多线程和序列化:

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