当一个类Java不复盖 哈希码(), 打印此类的一个实例提供了一个很好的独有的编号。

对如果是的话,为什么不试的对象说 哈希码():

尽可能合理实际的,哈希码定义的方法的类对象不返回不同的整数为不同的对象。

但是,当这类替代 哈希码(), 我怎么得到的 其独特的号码?

有帮助吗?

解决方案

System.identityHashCode(yourObject)会给yourObject的“原始的”哈希代码为整数。唯一性就不能保证。太阳JVM执行会给你这是关系到原来的内存地址,此对象的值,但是这是一个实现细节,你不应该依赖于它。

编辑:答案修改后遵循下面再汤姆的评论。存储器地址和移动对象。

其他提示

对如果是的话,为什么不试用对象规定,

这通常是通过转换实现内部的地址的对象为一个整数,但这个执行技术不需要通过Java™编程语言。

如果一级的复盖哈希码,这意味着,它希望产生一个具体的身份证明文件,其中将(一个可以希望)有权利的行为。

你可以使用 系统。identityHashCode 得到那个id,用于任何类。

也许这快,肮脏的解决方案是否行得通呢?

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

    public int hashCode() {
        return uid;
    }
}

这也给出了一个类初始化实例的数量。

hashCode()方法不是一个对象提供唯一的标识符。它,而消化对象的状态(即构件字段的值),以一个单一的整数。该值主要用于通过例如地图一些基于散列的数据结构,并设置以有效地存储和检索对象。

如果您需要为您的对象标识符,我建议你添加的,而不是压倒一切的hashCode你自己的方法。为了这个目的,可以象下面这样创建一个基本接口(或一个抽象类)。

public interface IdentifiedObject<I> {
    I getId();
}

用法示例:

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

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

    @Override
    public Integer getId() {
        return studentId;
    }
}

有关ID生成,您可以检查我的博客文章我试图解释一些方法来生成唯一的ID。

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

我想出了这个解决方案,它在我的情况,我对多线程创建的对象,并序列化的作品:

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;
    }
}
// looking for that last hex?
org.joda.DateTime@57110da6

如果你正在寻找进入hashcode Java类型,当你在对象上做一个.toString()底层代码是这样的:

Integer.toHexString(hashCode())

只是为了从不同的角度增大其他的答案。

如果你想重用来自“上面”的哈希码(S)和使用类的immutatable状态派生出新的,然后调用超会工作。虽然这可能/可能不会一路最多可级联的对象(即一些祖先可能不是超级调用),它可以让你通过重用派生哈希码。

@Override
public int hashCode() {
    int ancestorHash = super.hashCode();
    // now derive new hash from ancestorHash plus immutable instance vars (id fields)
}

有是hashCode()和identityHashCode()返回时之间的差。可能的是,对于两个不相等(与==测试)对象O1,O2的hashCode()可以是相同的。见下文如何,这是真实的例子中

class SeeDifferences
{
    public static void main(String[] args)
    {
        String s1 = "stackoverflow";
        String s2 = new String("stackoverflow");
        String s3 = "stackoverflow";
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
        System.out.println(s3.hashCode());
        System.out.println(System.identityHashCode(s1));
        System.out.println(System.identityHashCode(s2));
        System.out.println(System.identityHashCode(s3));
        if (s1 == s2)
        {
            System.out.println("s1 and s2 equal");
        } 
        else
        {
            System.out.println("s1 and s2 not equal");
        }
        if (s1 == s3)
        {
            System.out.println("s1 and s3 equal");
        }
        else
        {
            System.out.println("s1 and s3 not equal");
        }
    }
}

我有同样的问题,不满意任何答案至今,因为他们没有保证唯一的ID。

我也想打印对象ID用于调试旨意。我知道一定是有办法做到这一点,因为在Eclipse调试器,它指定为每个对象唯一的ID。

我一个解决方案提出了基于这样的事实,如果两个物体实际上是相同的实例“==”操作符的对象只返回true。

import java.util.HashMap;
import java.util.Map;

/**
 *  Utility for assigning a unique ID to objects and fetching objects given
 *  a specified ID
 */
public class ObjectIDBank {

    /**Singleton instance*/
    private static ObjectIDBank instance;

    /**Counting value to ensure unique incrementing IDs*/
    private long nextId = 1;

    /** Map from ObjectEntry to the objects corresponding ID*/
    private Map<ObjectEntry, Long> ids = new HashMap<ObjectEntry, Long>();

    /** Map from assigned IDs to their corresponding objects */
    private Map<Long, Object> objects = new HashMap<Long, Object>();

    /**Private constructor to ensure it is only instantiated by the singleton pattern*/
    private ObjectIDBank(){}

    /**Fetches the singleton instance of ObjectIDBank */
    public static ObjectIDBank instance() {
        if(instance == null)
            instance = new ObjectIDBank();

        return instance;
    }

    /** Fetches a unique ID for the specified object. If this method is called multiple
     * times with the same object, it is guaranteed to return the same value. It is also guaranteed
     * to never return the same value for different object instances (until we run out of IDs that can
     * be represented by a long of course)
     * @param obj The object instance for which we want to fetch an ID
     * @return Non zero unique ID or 0 if obj == null
     */
    public long getId(Object obj) {

        if(obj == null)
            return 0;

        ObjectEntry objEntry = new ObjectEntry(obj);

        if(!ids.containsKey(objEntry)) {
            ids.put(objEntry, nextId);
            objects.put(nextId++, obj);
        }

        return ids.get(objEntry);
    }

    /**
     * Fetches the object that has been assigned the specified ID, or null if no object is
     * assigned the given id
     * @param id Id of the object
     * @return The corresponding object or null
     */
    public Object getObject(long id) {
        return objects.get(id);
    }


    /**
     * Wrapper around an Object used as the key for the ids map. The wrapper is needed to
     * ensure that the equals method only returns true if the two objects are the same instance
     * and to ensure that the hash code is always the same for the same instance.
     */
    private class ObjectEntry {
        private Object obj;

        /** Instantiates an ObjectEntry wrapper around the specified object*/
        public ObjectEntry(Object obj) {
            this.obj = obj;
        }


        /** Returns true if and only if the objects contained in this wrapper and the other
         * wrapper are the exact same object (same instance, not just equivalent)*/
        @Override
        public boolean equals(Object other) {
            return obj == ((ObjectEntry)other).obj;
        }


        /**
         * Returns the contained object's identityHashCode. Note that identityHashCode values
         * are not guaranteed to be unique from object to object, but the hash code is guaranteed to
         * not change over time for a given instance of an Object.
         */
        @Override
        public int hashCode() {
            return System.identityHashCode(obj);
        }
    }
}

我认为,这应该能保证整个程序的生命周期唯一的ID。但是请注意,你可能不希望在生产应用中使用,是因为它保持引用所有你生成ID的对象。这意味着,对于其中创建的ID的任何对象将永远不会被垃圾收集。

由于我使用这个用于调试目的,我不是太关心内存被释放。

您可以修改此,以允许清理对象或移除各个对象如果释放存储器是一个问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top