Tôi đã có cùng một vấn đề và không hài lòng với bất kỳ câu trả lời nào cho đến nay vì không ai trong số họ đảm bảo ID duy nhất.
Tôi cũng muốn in ID đối tượng để gỡ lỗi có mục đích. Tôi biết rằng phải có một số cách để làm điều đó, bởi vì trong trình gỡ lỗi Eclipse, nó chỉ định các ID duy nhất cho mỗi đối tượng.
Tôi đã đưa ra một giải pháp dựa trên thực tế là toán tử "==" cho các đối tượng chỉ trả về true nếu hai đối tượng thực sự là cùng một thể hiện.
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);
}
}
}
Tôi tin rằng điều này sẽ đảm bảo ID duy nhất trong suốt vòng đời của chương trình. Tuy nhiên, lưu ý rằng có lẽ bạn không muốn sử dụng điều này trong một ứng dụng sản xuất vì nó duy trì các tham chiếu đến tất cả các đối tượng mà bạn tạo ID. Điều này có nghĩa là bất kỳ đối tượng nào bạn tạo ID sẽ không bao giờ được thu gom rác.
Vì tôi đang sử dụng điều này cho mục đích gỡ lỗi, tôi không quá quan tâm đến việc bộ nhớ được giải phóng.
Bạn có thể sửa đổi điều này để cho phép xóa Đối tượng hoặc xóa các đối tượng riêng lẻ nếu giải phóng bộ nhớ là một vấn đề đáng lo ngại.