Tại sao "ngắn ba mươi = 3 * 10" là một chuyển nhượng hợp pháp?


102

Nếu shortđược tự động thăng hạng inttrong các phép toán số học, thì tại sao lại là:

short thirty = 10 * 3;

Một chuyển nhượng hợp pháp cho shortbiến thirty?

Đổi lại, điều này:

short ten = 10;
short three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

cũng như điều này:

int ten = 10;
int three = 3;
short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED

không biên dịch vì không cho phép gán intgiá trị cho a shortmà không truyền như mong đợi.

Có điều gì đặc biệt đang xảy ra về các chữ số?


23
short thirty = 10 * 3;hầu hết có lẽ được thay thế bởi short thirty = 30;trình biên dịch, sau đó là một câu lệnh hợp lệ. (Tuy nhiên, tôi sẽ phải tra cứu phần JLS có liên quan).
Thomas

Trình biên dịch tính toán 10 * 3và khởi tạo biến với kết quả. Trong ví dụ không hoạt động của bạn, phép tính xảy ra trong thời gian chạy mà JVM truyền đoạn ngắn.
Felix

Tôi nghĩ đây là một bản sao của stackoverflow.com/questions/30346587/java-char-to-byte-casting hoặc stackoverflow.com/questions/9379983/… . Tuy nhiên: Lưu ý rằng final int ten = 10; final int three = 3; short thirty = ten * three;biên dịch tốt.
Marco 13

7
If short is automatically promoted to int in arithmetic operations- điều đó không liên quan. Cả 10hay 3là quần short cũng không phải là họ thăng chức, họ literals đang.
Ma-thi-ơ Đọc

@MatthewRead: nhưng ngay cả dưới dạng nghĩa đen, chúng phải được đánh giá như một kiểu dữ liệu cụ thể, phải không? Vậy có đúng như vậy không 103được đánh giá là ints bởi trình biên dịch?
LarsH

Câu trả lời:


139

Bởi vì trình biên dịch thay thế 10*3bằng 30 tại chính thời gian biên dịch . Vì vậy, hiệu quả: short thirty = 10 * 3được tính tại thời điểm biên dịch.

Hãy thử thay đổi tenthreeđể final short(làm cho chúng biên dịch các hằng số thời gian) và xem điều gì sẽ xảy ra: P

Kiểm tra mã byte bằng cách sử dụng javap -v cho cả verisions ( 10*3final short). Bạn sẽ có thể thấy rằng có rất ít sự khác biệt.

Ok, Vì vậy, đây là sự khác biệt mã byte cho các trường hợp khác nhau.

Trường hợp 1 :

Mã Java: main () {short s = 10 * 3; }

Mã byte:

stack=1, locals=2, args_size=1
         0: bipush        30  // directly push 30 into "s"
         2: istore_1      
         3: return   

Trường hợp -2:

public static void main(String arf[])  {
   final short s1= 10;
   final short s2 = 3;
   short s = s1*s2;
}

Mã byte:

  stack=1, locals=4, args_size=1
         0: bipush        10
         2: istore_1      
         3: iconst_3      
         4: istore_2      
         5: bipush        30 // AGAIN, push 30 directly into "s"
         7: istore_3      
         8: return   

Trường hợp -3:

public static void main(String arf[]) throws Exception {
     short s1= 10;
     short s2 = 3;
     int s = s1*s2;
}

Mã byte:

stack=2, locals=4, args_size=1
         0: bipush        10  // push constant 10
         2: istore_1      
         3: iconst_3        // use constant 3 
         4: istore_2      
         5: iload_1       
         6: iload_2       
         7: imul          
         8: istore_3      
         9: return 

Trong trường hợp trên, 103được lấy từ các biến cục bộ s1s2


17
thích Try changing ten and three to final shorttập thể dục :)
Sergey Pauk

1
@SergeyPauk - Đó là thực sự quan trọng trong việc hằng thời gian biên dịch hiểu biết .. áp dụng cho tất cả nguyên thủy (Strings cũng ..) :)
TheLostMind

1
@TheLostMind Tôi sẽ đề xuất một cách diễn đạt tốt hơn you will see that there's no difference (between those two lines in the decompiled code)vì đây không phải là ý của bạn sao?
Sergey Pauk

4
Thật thú vị, điều này cũng có nghĩa là điều đó case 10*3:và tương tự là hợp pháp trong cấu trúc công tắc.
Ceiling Gecko

5
Và tương tự trong cấu trúc enum. Trên thực tế, việc sử dụng những thứ như 1 << 5 cho các hằng số bitfield enum là điều không tưởng.
Bathsheba

18

Vâng, có điều gì đó đặc biệt đang xảy ra với trường hợp theo nghĩa đen: 10 * 3sẽ được đánh giá tại thời điểm biên dịch . Vì vậy, bạn không cần (short)chuyển đổi rõ ràng cho các ký tự được nhân lên.

ten * three không có giá trị thời gian biên dịch, do đó cần chuyển đổi rõ ràng.

Nó sẽ là một vấn đề khác nếu tenthreeđược đánh dấu final.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.