2009-02-24 29 views
83

Tôi muốn in "tham chiếu đối tượng" của một đối tượng trong Java cho mục đích gỡ lỗi. I.e. để đảm bảo rằng đối tượng giống nhau (hoặc khác nhau) tùy thuộc vào tình huống.Làm thế nào để bạn nhận được "tham chiếu đối tượng" của một đối tượng trong java khi toString() và hashCode() đã bị ghi đè?

Vấn đề là lớp trong câu hỏi được kế thừa từ một lớp khác, nó đã ghi đè cả toString() và hashCode() mà thường sẽ cho tôi id.

Ví dụ: Chạy một ứng dụng đa luồng, trong đó tôi (trong quá trình phát triển) muốn kiểm tra xem tất cả các chủ đề có sử dụng cùng một thể hiện của một đối tượng tài nguyên hay không.

+0

tùy thuộc vào nếu bạn có thể làm điều đó ở tất cả ... == là cách để đi ... nhưng tôi không có ý tưởng làm thế nào mã trong câu hỏi là stuctured. Một lần nữa hashCode là có khả năng tốt cho những gì bạn đang làm, nhưng nó có thể phá vỡ tùy thuộc vào cách thư viện được thực hiện. – TofuBeer

+0

Nó thực sự là một câu hỏi hay. –

Trả lời

84

biết chính xác là bạn có kế hoạch làm với nó (những gì bạn muốn làm nên sự khác biệt với những gì bạn sẽ cần phải gọi).

hashCode, theo quy định tại các JavaDocs, nói:

Càng nhiều càng tốt là hợp lý thực tế, phương thức hashCode định nghĩa bởi lớp Object không trở lại số nguyên phân biệt cho các đối tượng khác nhau. (Điều này thường được thực hiện bằng cách chuyển đổi địa chỉ nội bộ của đối tượng vào một số nguyên, nhưng kỹ thuật thực hiện điều này là không cần thiết bởi các ngôn ngữ lập trình Java ™.)

Vì vậy, nếu bạn đang sử dụng hashCode() để tìm hiểu xem đó là một đối tượng duy nhất trong bộ nhớ không phải là một cách hay để làm điều đó.

System.identityHashCode nào sau đây:

Trả về mã băm tương tự cho các đối tượng nhất định như sẽ được trả lại bởi hashCode phương pháp mặc định(), có hoặc không lớp đối tượng cho trước sẽ ghi đè hashCode(). Mã băm cho tham chiếu null là số không.

Mà, cho những gì bạn đang làm, nghe giống như những gì bạn muốn ... nhưng những gì bạn muốn làm có thể không an toàn tùy thuộc vào cách thư viện được triển khai.

+4

Tôi không hành động trên giá trị trong mã. Như pr. chỉnh sửa câu hỏi của tôi, tôi chỉ sử dụng nó cho mục đích gỡ lỗi của một tình huống nhất định. Đó là lý do tại sao tôi cảm thấy câu trả lời của tôi là hợp lý, nhưng tôi cung cấp cho bạn +1 để có câu trả lời sâu sắc. – Nicolai

+0

tỷ lệ cược là nó sẽ luôn luôn làm những gì bạn muốn - nhưng nó có thể phá vỡ trên một số máy ảo. – TofuBeer

+0

Nó sẽ bị hỏng (tức là identityHashCode sẽ không nhất thiết là duy nhất) trên bất kỳ máy ảo hợp lý nào. identityHashCode không phải là I.D. –

44

Đây là cách tôi giải quyết nó:

Integer.toHexString(System.identityHashCode(object)); 
+2

Điều này là không thực sự chính xác, vì nhiều đối tượng có thể trả về cùng một identityHashCode. – Robin

+2

Có đúng là hai đối tượng (tham chiếu) có cùng mã nhận dạng giống nhau không? đó là những gì để OP muốn – basszero

+2

Không, nó không phải là sự thật. Rất có thể, nhưng không được đảm bảo vì thông số KHÔNG xác định thuật toán. – Robin

3

Bạn không thể làm điều bạn muốn một cách an toàn vì hàm hashCode() mặc định có thể không trả về địa chỉ và đã được đề cập, nhiều đối tượng có cùng hashCode là có thể. Cách duy nhất để thực hiện những gì bạn muốn, là thực sự ghi đè phương thức hashCode() cho các đối tượng được đề cập và đảm bảo rằng tất cả chúng đều cung cấp các giá trị duy nhất. Cho dù điều này là khả thi trong tình huống của bạn là một câu hỏi khác.

Đối với bản ghi, tôi đã trải nghiệm nhiều đối tượng có cùng mã băm mặc định trong máy ảo IBM chạy trong máy chủ WS. Chúng tôi đã có một khiếm khuyết mà các đối tượng được đưa vào một bộ nhớ cache từ xa sẽ bị ghi đè vì điều này. Đó là một mở mắt cho tôi tại thời điểm đó vì tôi giả định hashcode mặc định là địa chỉ bộ nhớ đối tượng là tốt.

2

Thêm một id duy nhất cho tất cả các trường hợp của bạn, ví dụ:

public interface Idable { 
    int id(); 
} 

public class IdGenerator { 
    private static int id = 0; 
    public static synchronized int generate() { return id++; } 
} 

public abstract class AbstractSomething implements Idable { 
    private int id; 
    public AbstractSomething() { 
    this.id = IdGenerator.generate(); 
    } 
    public int id() { return id; } 
} 

Mở rộng từ AbstractSomething và truy vấn bất động sản này. Sẽ được an toàn bên trong một vm duy nhất (giả sử không có trò chơi chơi với các trình nạp lớp để có được xung quanh statics).

+0

Tôi có thể sử dụng AtomicInteger trong trường hợp này - nó có thông lượng cao hơn vì không cần đồng bộ hóa và nó sử dụng các hoạt động bộ nhớ nguyên tử được cung cấp bởi 'sun.misc.Unsafe' – RAnders00

8

Đôi bằng == sẽ luôn kiểm tra dựa trên nhận dạng đối tượng, bất kể việc triển khai mã băm hoặc bằng của đối tượng. Tất nhiên - hãy đảm bảo rằng các tham chiếu đối tượng bạn đang so sánh là volatile (trong một JVM 1,5+).

Nếu bạn thực sự phải có kết quả ToString đối tượng gốc (mặc dù đây không phải là giải pháp tốt nhất cho trường hợp sử dụng mẫu của bạn), thư viện Commons Lang có phương thức ObjectUtils.identityToString(Object) sẽ thực hiện những gì bạn muốn. Từ javadoc:

public static java.lang.String identityToString(java.lang.Object object) 

Gets toString đó sẽ là sản xuất bởi đối tượng nếu một lớp học không ghi đè toString riêng của mình. null sẽ trả về null.

ObjectUtils.identityToString(null)   = null 
ObjectUtils.identityToString("")   = "[email protected]" 
ObjectUtils.identityToString(Boolean.TRUE) = "[email protected]" 
+1

Nếu bạn đang sử dụng Java 7, thì bạn nên cân nhắc sử dụng [java.util.Objects] (http: // docs. oracle.com/javase/7/docs/api/java/util/Objects.html) – noahlz

+5

Mã này dựa trên 'identityHashCode'. – Brice

0

chúng ta có thể dễ dàng sao chép mã từ toString của lớp đối tượng để có được những tham chiếu của chuỗi

class Test 
{ 
    public static void main(String args[]) 
    { 
    String a="nikhil";  // it stores in String constant pool 
    String s=new String("nikhil"); //with new stores in heap 
    System.out.println(Integer.toHexString(System.identityHashCode(a))); 
    System.out.println(Integer.toHexString(System.identityHashCode(s))); 
    } 
} 
Các vấn đề liên quan