2016-03-26 11 views
9
int a = 2; 
int b = a + a; 

Class cache = Integer.class.getDeclaredClasses()[0]; 
Field myCache = cache.getDeclaredField("cache"); 
myCache.setAccessible(true); 

Integer[] newCache = (Integer[]) myCache.get(cache); 
newCache[132] = newCache[133]; 

System.out.printf("%d",b); // 5 
System.out.println(b); // 4 

Ở đây tôi thay đổi giá trị của cache[132] để cache[133] đó có nghĩa là hiện nay cache[132] == 5 trong printf() phương pháp nó in 5 tốt nhưng trong println() lý do tại sao nó in 4 nó sẽ là 5 lý do là những gì đằng sau vào nó?Lý do cho đầu ra khác nhau ở đây là gì?

+5

Bạn đang loay hoay với nội dung không có giấy tờ của một lớp thư viện - tại sao bạn mong đợi hành vi hợp lý ở đây? –

+4

Bạn đang sử dụng sự phản chiếu ở đây vì những gì dường như không có lý do thực sự tốt. Không rõ lý do tại sao bạn muốn làm điều này hoặc những gì bạn đang cố gắng thực hiện. Hơn nữa, khi bạn sử dụng sự phản chiếu, rất nhiều sự bảo đảm của trạng thái đối tượng và bất biến trở nên nhanh chóng vô hiệu, vì vậy hãy cẩn thận. – Makoto

+0

nếu bạn không biết lý do đó là tốt nhưng bạn không thể nói nó "khó chịu" @Oliver Charlesworth –

Trả lời

6

println có tình trạng quá tải chấp nhận int. Do đó trong dòng

System.out.println(b); 

các int không bao giờ được chuyển đổi thành một Object sử dụng Integer.valueOf.

printf có chữ ký

public PrintStream printf(String format, Object ... args) 

nên 4 được autoboxed đến Integer đối tượng 5 (sử dụng bộ nhớ cache sửa đổi), và do đó 5 được in ra.

+1

Khoản giữ này. Đây cũng là lý do tại sao tôi không thể nhìn thấy nó trong trình gỡ lỗi; hộp số tự động đã có hiệu lực khi 'printf' được gọi. – Makoto

1

Sau javap -verbose package.YourClassName

51: getstatic  #67     // Field java/lang/System.out:Ljava/io/PrintStream; 
    54: ldc   #73     // String %d 
    56: iconst_1 
    57: anewarray  #3     // class java/lang/Object 
    60: dup 
    61: iconst_0 
    62: iload_2 
    63: invokestatic #75     // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
    66: aastore 
    67: invokevirtual #79     // Method java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream; 
    70: pop 
    71: getstatic  #67     // Field java/lang/System.out:Ljava/io/PrintStream; 
    74: iload_2 
    75: invokevirtual #85     // Method java/io/PrintStream.println:(I)V 
    78: return 

Bạn thấy rằng tại hướng dẫn 63 Integer.valueOf được gọi là, do đó sử dụng bộ nhớ cache Integer. Tại điểm 75 chữ ký println không có một đối tượng mà là một int nguyên thủy thẳng, do đó không có bộ đệm ẩn Integer nào có liên quan.

1

Nếu bạn cố gắng mã dưới đây

System.out.println(Integer.valueOf(b)); 

Bạn sẽ thấy 5 được in cho việc này. Bây giờ cho phương thức printf bạn có dưới mã.

System.out.printf("%d",b); 

Nếu bạn thấy printf chấp nhận Chuỗi làm tham số đầu tiên và Đối tượng làm thông số thứ hai. Bạn có b là kiểu nguyên thủy (int). Auto boxing diễn ra và cho nó Integer.java class method : valueOf(int i) được sử dụng.

Ngoài ra nếu bạn khai báo Số nguyên thì bạn sẽ thấy 4 được in trong cả hai trường hợp khi không có tự động boxing xảy ra. thường -128 đến 127 được lưu trữ và bạn đã sửa đổi bộ nhớ cache nội bộ. valueOf sử dụng bộ nhớ cache và đó là lý do bạn thấy các đầu ra khác nhau

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