2010-09-03 25 views
106

Từ Java 1.5, bạn có thể trao đổi khá nhiều Integer với int trong nhiều trường hợp.Java: Số nguyên bằng hoặc ==

Tuy nhiên, tôi đã tìm thấy lỗi tiềm ẩn trong mã của mình khiến tôi ngạc nhiên một chút.

Các mã sau đây:

Integer cdiCt = ...; 
Integer cdsCt = ...; 
... 
if (cdiCt != null && cdsCt != null && cdiCt != cdsCt) 
    mismatch = true; 

dường như được thiết lập không đúng cách không phù hợp khi các giá trị là như nhau, mặc dù tôi không thể xác định trong hoàn cảnh nào. Tôi đặt một breakpoint trong Eclipse và thấy rằng các giá trị Integer là cả 137, và tôi kiểm tra biểu thức boolean và nó nói nó là sai, nhưng khi tôi bước qua nó, nó đã thiết lập không khớp với đúng.

Thay đổi điều kiện để:

if (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt)) 

cố định vấn đề.

Có ai có thể tiết lộ một số lý do tại sao điều này xảy ra không? Cho đến nay, tôi đã chỉ nhìn thấy hành vi trên localhost của tôi trên máy tính của riêng tôi. Trong trường hợp cụ thể này, mã đã thực hiện thành công nó qua khoảng 20 lần so sánh, nhưng thất bại trên 2. Vấn đề đã được lặp lại liên tục.

Nếu nó là một vấn đề phổ biến, nó sẽ gây ra lỗi trên môi trường khác của chúng tôi (dev và thử nghiệm), nhưng cho đến nay, không ai báo cáo vấn đề sau hàng trăm thử nghiệm thực thi đoạn mã này.

Vẫn không hợp pháp để sử dụng == để so sánh hai giá trị Integer?

Ngoài tất cả các câu trả lời tốt dưới đây, liên kết xếp chồng lên nhau sau đây có khá nhiều thông tin bổ sung. Nó thực sự sẽ trả lời câu hỏi ban đầu của tôi, nhưng vì tôi không đề cập đến autoboxing trong câu hỏi của tôi, nó đã không xuất hiện trong các đề xuất đã chọn:

Why can't the compiler/JVM just make autoboxing “just work”?

Trả lời

177

JVM đang lưu vào bộ nhớ cache Giá trị nguyên. == chỉ hoạt động cho số giữa -128 và 127 http://www.owasp.org/index.php/Java_gotchas#Immutable_Objects_.2F_Wrapper_Class_Caching

+1

Cảm ơn, điều đó chắc chắn giải thích vì sao 137 thất bại! Và nó cũng trả lời câu hỏi của tôi về lý do tại sao nó không phải là một vấn đề phổ biến, trong 95% các trường hợp tôi sẽ gặp phải, giá trị sẽ dưới 127. Tốt để bắt này ngay bây giờ mặc dù cho 5% mà nó không phải là. –

+0

Lưu ý thú vị: cho đến một vài tuần trước, cdiCt và cdsCt là cả hai ints vì vậy điều này là tốt, nhưng tôi đã phải làm cho họ số nguyên để kiểm tra tình hình null được xử lý khác nhau ... –

+2

@Jeremy Yeah, đó là một vấn đề khá mơ hồ, nhưng như một quy tắc chung bạn sử dụng .equals() cho các đối tượng và == cho nguyên thủy. Bạn không thể dựa vào autounboxing để kiểm tra bình đẳng. – Adam

5

Vấn đề là hai đối tượng Integer của bạn chỉ là, đồ vật. Chúng không khớp vì bạn đang so sánh hai tham chiếu đối tượng của bạn, chứ không phải các giá trị bên trong. Rõ ràng .equals được ghi đè để cung cấp một so sánh giá trị như trái ngược với một so sánh tham chiếu đối tượng.

+0

Tốt câu trả lời, nhưng nó không giải thích lý do tại sao nó chỉ không cho 137. –

+0

Doh, tôi đã bỏ lỡ phần đó. – MattC

4

Integer đề cập đến tham chiếu, nghĩa là khi so sánh các tham chiếu bạn đang so sánh nếu chúng trỏ đến cùng một đối tượng, không phải giá trị. Do đó, vấn đề bạn đang thấy. Lý do nó hoạt động rất tốt với các loại đồng bằng int là nó unboxes giá trị chứa bởi các Integer.

Tôi có thể thêm rằng nếu bạn đang làm những gì bạn đang làm, tại sao có câu hỏi if để bắt đầu?

mismatch = (cdiCt != null && cdsCt != null && !cdiCt.equals(cdsCt)); 
+2

Điểm tốt, nhưng tôi không làm những gì tôi đang làm. Nó đã được đơn giản hóa. –

+0

Đây là cách viết mã và đây là câu trả lời được chấp nhận. ** Luôn ** so sánh các đối tượng bằng .equals(). Tại sao lại sử dụng số nguyên được lưu trong bộ nhớ cache và để mã của bạn có cơ hội? – NobleUplift

61

Bạn không thể so sánh hai Integer với một đơn giản == họ đang vật nên hầu hết các tài liệu tham khảo thời gian sẽ không giống nhau.

Có một mẹo, với Integer giữa -128 và 127, tham chiếu sẽ giống như sử dụng hộp số tự động Integer.valueOf() lưu trữ các số nguyên nhỏ.

Nếu giá trị p được đóng là đúng, sai, byte, char trong phạm vi \ u0000 thành \ u007f hoặc số int hoặc ngắn giữa -128 và 127, thì hãy để r1 và r2 là kết quả của bất kỳ chuyển đổi đấm bốc nào của p. Nó luôn luôn là trường hợp r1 == r2.


Resources:

Cùng chủ đề:

+0

Cảm ơn, tôi đã đánh dấu câu trả lời đầu tiên là câu trả lời đúng. –

+0

oh, tôi đoán tôi có thể đánh dấu cả hai là đúng. Đánh dấu chọn cho bạn. –

+0

@ Jeremy, thực ra bạn chỉ có thể đánh dấu một cái là đúng. Nhấp vào dấu chọn lần thứ hai chỉ thay đổi câu trả lời được chấp nhận. Không được nhỏ; Câu trả lời của Colin là tuyệt vời. :) – Adam

1

"==" luôn so sánh vị trí bộ nhớ hoặc tham chiếu đối tượng của giá trị. bằng phương pháp luôn so sánh các giá trị. Nhưng bằng cũng gián tiếp sử dụng toán tử "==" để so sánh các giá trị.

Sử dụng số nguyên Bộ đệm ẩn để lưu trữ các giá trị từ -128 đến +127. Nếu toán tử == được sử dụng để kiểm tra bất kỳ giá trị nào trong khoảng từ -128 đến 127 thì nó trả về giá trị true. cho các giá trị khác, nó trả về false.

Tham khảo các link đối với một số thông tin bổ sung