Mengapa "int i = 2147483647 +1;" OK, tapi “byte b = 127 +1;” tidak bisa dikompilasi?

126

Mengapa tidak int i = 2147483647 + 1;apa - apa, tetapi byte b = 127 + 1;tidak dapat dikompilasi?

goku
sumber
16
Saya juga memiliki keraguan: mengapa bytetipe data sangat menyakitkan ?!
BoltClock
9
ini jelas merupakan kesalahan desain yang byteditandatangani alih-alih tidak ditandatangani.
dikembalikan
4
@BoltClock Ini hanya menyakitkan ketika Anda tidak tahu bagaimana menggunakannya dengan benar. stackoverflow.com/questions/397867/…
starblue
2
@ starblue, apakah ada contoh nyata di mana tipe byte Java berlaku?
Thorbjørn Ravn Andersen
Jika ada data yang ditentukan sebagai byte kemudian gunakan Java byteuntuk kejelasan, misalnya dalam parameter. Dalam hal ini fakta bahwa Anda tidak dapat menetapkan intnilai bahkan akan menangkap beberapa bug. Atau gunakan byteuntuk menghemat ruang dalam array. Saya tidak akan menggunakan byteuntuk nilai tunggal yang kebetulan muat dalam satu byte.
starblue

Jawaban:

172

Konstanta dievaluasi sebagai int, sehingga 2147483647 + 1meluap dan memberi Anda int baru, yang dapat ditetapkan int, sementara 127 + 1juga dievaluasi intsama dengan 128, dan tidak dapat ditetapkan byte.

MByD
sumber
10
Sebenarnya, hari ini saya membaca beberapa teka-teki Jawa , termasuk sebuah teka-teki tentang hal itu ... Lihat di sini: javapuzzlers.com/java-puzzlers-sampler.pdf - puzzle 3
MByD
3
Masalahnya adalah jenis intkarena promosi numerik biner, nilainya 127adalah herring merah.
starblue
Saya lebih suka konstanta dievaluasi dengan presisi tak terbatas dan juga memberikan kesalahan pada int i = 2147483647 +1;
Eduardo
@ MByD: Seperti yang Anda katakan " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", apakah ini berarti bahwa 50 +1 akan dievaluasi bytedan karenanya dapat ditugaskan byte?
Bhushan
1
@ 10101010 - tidak tepat. itu akan ditugaskan untuk byte, tetapi pertama-tama (sesuai dengan standar) akan dievaluasi sebagai int.
MByD
35

Huruf 127 menunjukkan nilai tipe int. Begitu juga dengan literal 1. Jumlah keduanya adalah bilangan bulat 128. Masalahnya, dalam kasus kedua, adalah bahwa Anda menetapkan ini ke variabel tipe byte. Itu tidak ada hubungannya dengan nilai aktual dari ekspresi. Ini ada hubungannya dengan Java yang tidak mendukung paksaan (*). Anda harus menambahkan typecast

byte b = (byte)(127 + 1);

dan kemudian mengkompilasi.

(*) setidaknya bukan dari jenis String-to-integer, float-to-Time, ... Java memang mendukung paksaan jika mereka, dalam arti, non-loss (Java menyebut ini "pelebaran").

Dan tidak, kata "paksaan" tidak perlu dikoreksi. Itu dipilih dengan sangat sengaja dan benar pada saat itu. Dari sumber terdekat ke tangan (Wikipedia): "Dalam kebanyakan bahasa, kata paksaan digunakan untuk menunjukkan konversi tersirat , baik selama kompilasi atau selama waktu berjalan." dan "Dalam ilmu komputer, konversi tipe, typecasting, dan paksaan adalah cara yang berbeda , secara implisit atau eksplisit, mengubah entitas dari satu tipe data menjadi yang lain.".

Erwin Smout
sumber
Contoh kode Anda mungkin harus byte b = (byte) 127 + 1; yang merupakan 'Tambahkan 1 ke nilai byte maksimal', contoh Anda hanya mengubah nilai int 128 menjadi nilai byte.
NKCSS
6
@NKCSS - Saya tidak berpikir Anda benar, ini - (byte)(127 + 1)melemparkan 128 (integer) ke byte, sementara ini (byte)127 + 1melemparkan 127 ke byte, tetapi sekali lagi ke int, karena ditambahkan ke 1 (int) dan Anda dapatkan 128 (int) dan kesalahan tetap.
MByD
6

Sebagai bukti untuk @MByD:

Kode ini mengkompilasi:

byte c = (byte)(127 + 1);

Karena meskipun ekspresi (127 + 1)adalah int dan di luar cakupan dari bytetipe hasilnya dicor byte. Ungkapan ini menghasilkan -128.

AlexR
sumber
3

JLS3 # 5.2 Konversi Tugas

(variabel = ekspresi)

Selain itu, jika ekspresi adalah ekspresi konstan (§15.28) dari tipe byte, pendek, karakter atau int:

Konversi penyempitan primitif dapat digunakan jika jenis variabelnya adalah byte, pendek, atau char, dan nilai ekspresi konstan dapat diwakili dalam jenis variabel.


Tanpa klausa ini, kita tidak akan bisa menulis

byte x = 0;
char c = 0;

Tetapi haruskah kita dapat melakukan ini? Saya kira tidak. Ada beberapa keajaiban yang terjadi dalam pertobatan di antara kaum primitif, seseorang harus sangat berhati-hati. Saya akan keluar dari cara saya untuk menulis

byte x = (byte)0;
tak dapat disangkal
sumber
untuk pertanyaan yang harus kita dapat ... saya tidak melihat ada yang salah dengan byte x = 0tetapi sekali lagi, saya seorang programmer C.
Grady Player
Saya mungkin bisa melihat argumen terhadap char c = 0, tetapi mengapa byte x = 0 salah?
Michael Burge
Ini menyesatkan mata yang tidak terlatih, berpikir mereka menetapkan byte 0 ke variabel byte. Tidak banyak bahaya dalam contoh ini, tetapi secara umum, beroperasi pada byte / short / char bisa sangat membingungkan karena konversi tersirat. Mereka jauh lebih rumit daripada yang orang pikirkan. Saya ingin kejelasan sebanyak mungkin dalam kode saya, jangan memperkenalkan ketidakpastian apa pun demi menyelamatkan beberapa goresan kunci.
diperbaiki
Apakah aturan yang sama berlaku ketika konversi primitif penyempitan adalah dari panjang ke int, mis. Int i = 1 + 0L? Hanya bertanya karena teks yang Anda kutip secara eksplisit mengabaikan hal itu.
Erwin Smout
@ Erwin tidak, int i=0Litu ilegal.
diperbaiki