2013-07-05 42 views
7

Tôi so sánh 2 đoạn mã. Đầu tiênSố nguyên i = 3 và Số nguyên i = Số nguyên mới (3)

Integer i=3; 
Integer j=3; 
if(i==j) 
    System.out.println("i==j"); //prints i==j    

Thứ hai,

Integer i=3; 
Integer j=new Integer(3); 
if(i==j) 
    System.out.println("i==j"); // does not print 

Tôi đã nghi ngờ rằng trong đoạn đầu tiên tại sao i==j đang được in? Các tham chiếu có khác nhau không?

+0

Một số việc cần làm với refernece, new, Objects, compairing memory addresses #Idk # CIS20 ... Somthing –

+0

'==' so sánh tham chiếu không phải giá trị khi bạn gán. Trong trường hợp nắm tay cả hai 'i',' j' trỏ đến cùng số nguyên trong bộ nhớ. trong trường hợp thứ hai sử dụng mới, bạn tạo hai thể hiện mới của số nguyên đối tượng có cùng giá trị 3. –

+0

Đây không phải là bản sao của câu hỏi được liên kết. Lưu ý rằng câu hỏi đã được đóng lại như là một "câu hỏi không thực sự" do một tiền đề sai lầm rằng 'new Integer (1) == new Integer (1)', điều đó không đúng. –

Trả lời

0

Bởi vì trong mã thứ hai của mã số nguyên đầu tiên của bạn đang được tự động đóng hộp trong khi số thứ hai không phải là.

Điều này có nghĩa là một phiên bản Integer mới đang được tạo khi đang di chuyển. Hai trường hợp đối tượng này là khác nhau. Kiểm tra bình đẳng sẽ trả về false ở đó vì hai cá thể thực sự là những phần khác nhau của bộ nhớ.

+1

Không, đó là đoạn mã * đầu tiên * đang sử dụng autoboxing trong cả hai trường hợp; thứ hai chỉ sử dụng nó cho giá trị đầu tiên. –

+0

Tôi đã đề cập đến số nguyên đầu tiên, không phải là số nguyên thứ hai. –

+0

Điều đó cực kỳ không rõ ràng. It's * still * không rõ ràng từ câu trả lời này tại sao đoạn mã đầu tiên in "i == j", bởi vì bạn chưa giải thích bất cứ điều gì về bản chất bộ nhớ đệm của boxing. –

1

Không, chúng không nên, vì java có thể sử dụng các đối tượng Integer được tạo sẵn cho các số nhỏ khi autoboxing.

5

Số nguyên của các nhóm Java giữa -128 và 127 và do đó cả hai tham chiếu đều giống nhau.

Integer i=3; 
Integer j=3; 

Điều này dẫn đến autoboxing và 3 được chuyển thành Integer 3. Vì vậy, cho tôi là đề cập đến một đối tượng Integer đó là trong hồ bơi thường xuyên, bây giờ khi bạn làm j = 3, tài liệu tham khảo giống như của tôi là được gán cho j.

Trong khi đó bên dưới mã:

Integer j=new Integer(3); 

luôn kết quả trong một tạo Integer mới, trong heap. Điều này không được gộp lại. Và do đó bạn thấy rằng cả hai tham chiếu đều đề cập đến các đối tượng khác nhau. Kết quả nào trong

Integer i=3; 
Integer j=new Integer(3); 
if(i==j) 
    System.out.println("i==j"); // **does not print** 
+0

... trong trường hợp đầu tiên. –

0

Trình tối ưu hóa thông dịch viên/JIT có thể đặt tất cả 3 vào cùng một hộp. Nhưng nếu bạn buộc một "mới" thì bạn sẽ nhận được một địa chỉ khác.

Hãy thử

j=8; // after initialization of i and j 

sau đó xem địa chỉ của j thay đổi cho phiên bản đầu tiên.

19

Nó liên quan đến cách thức hoạt động của boxing. Từ JLS section 5.1.7:

Nếu p giá trị được đóng hộp là đúng, sai, một byte, hoặc một char trong khoảng \ u0000 để \ u007f, hoặc một int hoặc số ngắn giữa -128 và 127 (bao gồm) , sau đó cho 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.

Về cơ bản, một Java thực hiện phải bộ nhớ cache cơ quan đại diện đóng hộp cho các giá trị phù hợp nhỏ, và có thể bộ nhớ cache hơn. Toán tử == chỉ so sánh các tham chiếu, do đó, nó đặc biệt phát hiện xem hai biến đó có tham chiếu đến cùng một đối tượng hay không. Trong đoạn mã thứ hai họ chắc chắn sẽ không, vì new Integer(3) chắc chắn không phải là tham chiếu tương tự như bất kỳ phần nào được tạo trước đó ... nó luôn tạo một đối tượng mới.

Do các quy tắc trên, mã này luôn phải đưa ra cùng một kết quả:

Integer x = 127; 
Integer y = 127; 
System.out.println(x == y); // Guarantee to print true 

Trong khi điều này có thể đi một trong hai cách:

Integer x = 128; 
Integer y = 128; 
System.out.println(x == y); // Might print true, might print false 
+0

Bạn nên giải thích so sánh ==. –

+0

Tại sao điều này lại được bình chọn? – jason

+2

@William Morrison: Không đồng ý. OP rõ ràng đã nhận được rằng '==' là tham chiếu bình đẳng. Vấn đề là ông nhầm tưởng rằng các tham chiếu là khác nhau (có nghĩa là, khái niệm còn thiếu ở đây là "interning" đối với một số nguyên thủy, không phải grokking '=='). – jason

0

Trong một thời trang tương tự để chuỗi, khi autoboxing được sử dụng, chẳng hạn như trong

Integer i = 3; 
Integer j = 3; 

Java có thể rút w từ một hồ vật đúc sẵn. Trong trường hợp của j, đã có một trường hợp Integer đại diện cho giá trị của 3 trong hồ bơi, do đó, nó rút ra từ đó. Do đó, ij trỏ đến cùng một điều, do đó i == j.

Trong ví dụ thứ hai của bạn, bạn đang rõ ràng instantiating một đối tượng mới Integer cho j, vì vậy ij điểm với các đối tượng khác nhau, do đó i != j.

2

Tôi có nghi ngờ rằng trong đoạn đầu tiên tại sao i == j đang được in? Các tham chiếu có khác nhau không?

Bởi vì,

Integer i=3; 
    Integer j=3; 

được nội sử dụng Integer#valueOf() để thực hiện autoBoxing. Và oracle doc nói về phương thức valueOf() rằng:

Trả về một thể hiện Integer đại diện cho giá trị int được chỉ định. Nếu không cần trường hợp Số nguyên mới, thì phương pháp này thường là được sử dụng ưu tiên cho hàm tạo Integer (int), vì phương pháp này là có khả năng mang lại hiệu suất thời gian và không gian tốt hơn đáng kể theo số. Phương pháp này sẽ luôn luôn lưu các giá trị trong phạm vi từ -128 đến 127, bao gồm và có thể lưu các giá trị khác ngoài phạm vi này.

Kể từ khi giá trị 3 do đó lưu trữ, cả hai biến ij đang tham chiếu cùng một đối tượng. Vì vậy, i==j đang trả lại true. Integer#valueOf() sử dụng flyweight pattern.

2
Integer i=3; 
Integer j=3; 
if(i==j)System.out.println("i==j"); 

Ở đây, 3 đang được tự động đóng hộp và do đó ij điểm với cùng Integer.

Integer i=3; 
Integer j=new Integer(3); 
if(i==j)System.out.println("i==j"); // does not print 

Ở đây, i điểm đến Integer trong khi j điểm tự động đóng hộp đến một mới Integer và do đó có tài liệu tham khảo không kiểm tra hành bình đẳng ==.

Nhưng, đây là một số thực phẩm bổ sung cho tư tưởng.

Integer i=300; 
Integer j=300; 
if(i!=j)System.out.println("i!=j"); // prints i!=j 

Tại sao? Bởi vì, auto-boxing chỉ chia sẻ Integer trường hợp từ -128 đến 127. Tuy nhiên, hành vi này có thể khác nhau giữa các triển khai Java khác nhau.

+0

' Integer' của pooling không được thực hiện bởi JVM.Nó hoàn toàn được thực hiện bởi 'Integer'. Xem mã nguồn' Integer'. –

+0

@SteveKuo Tôi vừa kiểm tra 'Integer.valueOf()' và có phạm vi được giới hạn bởi 'Integer' từ -128 đến' IntegerCache.high' (127) .Tôi đã sửa câu trả lời của mình. –

0

Trong Sau Piece of Code:

Integer i=3; 
Integer j=3; 
if(i==j) 
    System.out.println("i==j"); 

Ở đây, "==" so sánh tài liệu tham khảo với nhau chứ không phải là giá trị. Vì vậy, số nguyên i và j đều tham chiếu cùng một tham chiếu trong bộ nhớ.

trong khi ở sau Piece of Code:

Integer i=3; 
Integer j=new Integer(3); 
if(i==j) 
    System.out.println("i==j"); 

Các tài liệu tham khảo cho cả hai giá trị này được thay đổi vì 'j' mới được tạo ra đối tượng/tài liệu tham khảo của Integer trong bộ nhớ trong khi 'i' là chỉ đề cập đến một giá trị.

Do đó, đầu ra của mã thứ nhất là "i == j" và mã thứ 2 không có bất kỳ đầu ra nào.

Hy vọng điều này sẽ hữu ích.

Các vấn đề liên quan