Mengapa "short three = 3 * 10" merupakan tugas hukum?


102

Jika shortsecara otomatis dipromosikan ke intdalam operasi aritmatika, mengapa:

short thirty = 10 * 3;

Penugasan hukum untuk shortvariabel thirty?

Selanjutnya, ini:

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

serta ini:

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

tidak dapat dikompilasi karena menetapkan intnilai ke a shorttidak diperbolehkan tanpa melakukan cast seperti yang diharapkan.

Apakah ada sesuatu yang istimewa tentang literal numerik?


23
short thirty = 10 * 3;kemungkinan besar digantikan oleh short thirty = 30;kompiler yang kemudian merupakan pernyataan yang valid. (Saya harus mencari bagian JLS yang relevan).
Thomas

Kompilator menghitung 10 * 3dan menginisialisasi variabel dengan hasilnya. Dalam contoh non-kerja Anda, penghitungan terjadi pada waktu proses di mana JVM mentransmisikan short.
Felix

Saya pikir ini adalah duplikat, dari stackoverflow.com/questions/30346587/java-char-to-byte-casting atau stackoverflow.com/questions/9379983/… . Namun: Perhatikan bahwa final int ten = 10; final int three = 3; short thirty = ten * three;mengkompilasi dengan baik.
Marco13

7
If short is automatically promoted to int in arithmetic operations- itu tidak relevan. Baik 10atau 3yang celana pendek mereka juga tidak dipromosikan, mereka literal.
Matius Baca

@ MatthewRead: tetapi bahkan sebagai literal, mereka harus dievaluasi sebagai tipe data tertentu, bukan? Jadi apakah benar itu 10dan 3dievaluasi sebagai intoleh kompilator?
LarsH

Jawaban:


139

Karena kompilator mengganti 10*3dengan 30 pada waktu kompilasi itu sendiri. Jadi, efektif: short thirty = 10 * 3dihitung pada waktu kompilasi.

Coba ubah tendan threeke final short(buat mereka menyusun konstanta waktu) dan lihat apa yang terjadi: P

Periksa kode byte yang digunakan javap -v untuk kedua verisi ( 10*3dan final short). Anda akan dapat melihat bahwa ada sedikit perbedaan.

Oke, Jadi, inilah perbedaan kode byte untuk kasus yang berbeda.

Kasus 1 :

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

Kode byte:

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

Kasus -2:

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

Kode 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   

Kasus -3:

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

Kode 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 

Dalam kasus di atas, 10dan 3diambil dari variabel lokal s1dans2


17
menyukai Try changing ten and three to final shortlatihan :)
Sergey Pauk

1
@SergeyPauk - Itu sangat penting dalam memahami konstanta waktu kompilasi .. berlaku untuk semua primitif (String juga ..) :)
TheLostMind

1
@TheLostMind Saya akan menyarankan you will see that there's no difference (between those two lines in the decompiled code)penyebab kata-kata yang lebih baik bukankah ini maksud Anda?
Sergey Pauk

4
Menariknya, ini juga berarti bahwa case 10*3:dan sejenisnya legal dalam konstruksi sakelar.
Ceiling Gecko

5
Dan serupa dalam konstruksi enum. Faktanya, menggunakan hal-hal seperti 1 << 5 untuk konstanta enum bitfield adalah idiomatik.
Batsyeba

18

Ya, ada sesuatu yang istimewa yang terjadi dengan kasus literal: 10 * 3akan dievaluasi pada waktu kompilasi . Jadi, Anda tidak memerlukan (short)konversi eksplisit untuk literal yang dikalikan.

ten * three bukan waktu kompilasi yang dapat dievaluasi sehingga membutuhkan konversi eksplisit.

Ini akan menjadi masalah yang berbeda jika tendan threeditandai final.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.