Tại sao là int int i = 2147483647 + 1; OK, nhưng byte byte b = 127 + 1; không thể biên dịch được?


126

Tại sao không sao int i = 2147483647 + 1;, nhưng byte b = 127 + 1;không thể biên dịch được?


16
Tôi cũng có một nghi ngờ thực sự: tại sao bytekiểu dữ liệu lại đau như vậy?!
BoltClock

9
Đó chắc chắn là một lỗi thiết kế byteđược ký thay vì không dấu.
chối cãi

4
@BoltClock Chỉ là một nỗi đau khi bạn không biết sử dụng nó đúng cách. stackoverflow.com/questions/397867/
Mạnh

2
@starblue, có ví dụ thực tế nào trong đó loại byte Java được áp dụng không?
Thorbjørn Ravn Andersen

Nếu có dữ liệu được chỉ định là byte thì hãy sử dụng Java bytecho rõ ràng, ví dụ như trong các tham số. Trong trường hợp đó, thực tế là bạn không thể gán intgiá trị thậm chí sẽ bắt một số lỗi. Hoặc sử dụng byteđể tiết kiệm không gian trong mảng. Tôi sẽ không sử dụng bytecho một giá trị duy nhất phù hợp với một byte.
starblue

Câu trả lời:


172

Các hằng số được đánh giá là 2147483647 + 1int , vì vậy tràn và cung cấp cho bạn một int mới, có thể gán được int, trong khi 127 + 1cũng được đánh giá là intbằng 128, và nó không thể gán được byte.


10
Trên thực tế, hôm nay tôi đã đọc một số câu đố Java , bao gồm cả câu đố về điều đó ... Xem tại đây: javapuzzlers.com/java-puzzlers-sampler.pdf - câu đố 3
MByD

3
Vấn đề là loại intdo quảng cáo số nhị phân, giá trị 127là cá trích đỏ.
starblue

Tôi muốn các hằng số được đánh giá với độ chính xác vô hạn và cũng đưa ra lỗi trên int i = 2147483647 + 1;
Eduardo

@MByD: Như bạn đã nói " while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.", điều này có nghĩa là 50 + 1 sẽ được đánh giá là bytevà do đó có thể được gán cho byte?
Bhushan

1
@ 10101010 - không chính xác. nó sẽ được gán cho byte, nhưng trước tiên (theo tiêu chuẩn) nó sẽ được đánh giá là int.
MByD

35

Chữ 127 biểu thị một giá trị của kiểu int. Chữ 1. cũng vậy, tổng của hai số này là số nguyên 128. Vấn đề, trong trường hợp thứ hai, là bạn đang gán giá trị này cho một biến kiểu byte. Nó không có gì để làm với giá trị thực tế của các biểu thức. Nó phải làm với Java không hỗ trợ các ép buộc (*). Bạn phải thêm một kiểu chữ

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

và sau đó nó biên dịch.

(*) ít nhất không phải là kiểu String-to-integ, float-to-Time, ... Java không hỗ trợ các cưỡng chế nếu theo nghĩa nào đó, chúng không bị mất (Java gọi đây là "mở rộng").

Và không, từ "ép buộc" không cần sửa. Nó đã được lựa chọn rất có chủ ý và chính xác tại đó. Từ nguồn gần nhất đến tay (Wikipedia): "Trong hầu hết các ngôn ngữ, từ cưỡng chế được sử dụng để biểu thị một chuyển đổi ngầm , trong quá trình biên dịch hoặc trong thời gian chạy." và "Trong khoa học máy tính, chuyển đổi kiểu, đánh máy và ép buộc là những cách khác nhau, ngầm hoặc rõ ràng, thay đổi một thực thể của một loại dữ liệu thành một loại dữ liệu khác."


Ví dụ mã của bạn có thể phải là byte b = (byte) 127 + 1; đó là 'Thêm 1 vào giá trị byte tối đa', ví dụ của bạn chỉ biến giá trị int 128 thành giá trị byte.
NKCSS

6
@NKCSS - Tôi không nghĩ bạn đúng, điều này - chuyển (byte)(127 + 1)128 (số nguyên) thành một byte, trong khi điều này (byte)127 + 1chuyển 127 thành một byte, nhưng sau đó lại chuyển sang int, vì nó được thêm vào 1 (int) và bạn nhận được 128 (int) và lỗi ở lại.
MByD

6

Để làm bằng chứng cho @MByD:

Các mã sau biên dịch:

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

Bởi vì mặc dù biểu thức (127 + 1)là int và vượt quá phạm vi tắt byte, kết quả được truyền tới byte. Biểu thức này tạo ra -128.


3

Chuyển đổi bài tập JLS3 # 5.2

(biến = biểu thức)

Ngoài ra, nếu biểu thức là biểu thức không đổi (§15.28) của kiểu byte, short, char hoặc int:

Một chuyển đổi nguyên thủy thu hẹp có thể được sử dụng nếu loại biến là byte, ngắn hoặc char và giá trị của biểu thức hằng có thể biểu diễn trong loại biến.


Không có điều khoản này, chúng tôi sẽ không thể viết

byte x = 0;
char c = 0;

Nhưng chúng ta có thể làm điều này? Tôi không nghĩ vậy. Có khá nhiều phép thuật đang diễn ra trong quá trình chuyển đổi giữa các nguyên thủy, người ta phải rất cẩn thận. Tôi sẽ đi ra ngoài để viết

byte x = (byte)0;

đối với câu hỏi chúng ta có thể ... tôi không thấy có gì sai trái cả byte x = 0nhưng sau đó, tôi lại là một lập trình viên C.
Người chơi Grady

Tôi có thể thấy một đối số chống lại char c = 0, nhưng tại sao byte x = 0 sai?
Michael Burge

Nó gây hiểu lầm cho đôi mắt không được huấn luyện, nghĩ rằng họ đang gán một byte 0 cho một biến byte. Không có nhiều tác hại trong ví dụ này, nhưng nói chung, hoạt động trên byte / short / char có thể rất khó hiểu do chuyển đổi ngầm định. Chúng phức tạp hơn nhiều so với mọi người nghĩ. Tôi muốn càng rõ ràng càng tốt trong mã của mình, đừng đưa ra bất kỳ sự không chắc chắn nào vì mục đích lưu một vài nét chính.
chối cãi

Có một quy tắc tương tự áp dụng khi chuyển đổi nguyên thủy thu hẹp từ dài sang int, ví dụ int i = 1 + 0L không? Chỉ cần hỏi bởi vì văn bản trích dẫn của bạn rõ ràng bỏ trường hợp đó ra.
Erwin Smout

@Erwin không, int i=0Llà bất hợp pháp.
chối cãi
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.