2011-10-21 12 views
16

thể trùng lặp:
Varying behavior for possible loss of precisionJava phá vỡ gõ mạnh mẽ! Ai có thể giải thích nó?

Tôi tìm thấy một không thống nhất trong Java kiểm tra kiểu mạnh tại thời gian biên dịch. Vui lòng xem mã sau:

int sum = 0; 
sum = 1; //is is OK 
sum = 0.56786; //compile error because of precision loss, and strong typing 
sum = sum + 2; //it is OK 
sum += 2; //it is OK 
sum = sum + 0.56787; //compile error again because of automatic conversion into double, and possible precision loss 
sum += 0.56787; //this line is does the same thing as the previous line, but it does not give us a compile error, and javac does not complain about precision loss etc. 

Có ai có thể giải thích cho tôi không? Có phải đó là lỗi đã biết hoặc hành vi mong muốn không? C++ đưa ra cảnh báo, C# đưa ra một lỗi biên dịch.

Java có đánh mạnh không? Bạn có thể thay thế + = bằng - = hoặc * = - mọi thứ đều được trình biên dịch chấp nhận.

+0

lạ là bạn đang lưu trữ phao trong int biến –

+3

@ KarelFrajtak Một số thập phân mà không có một công cụ sửa đổi (như 'd' hoặc' f') là một số hai, không phải là một phao. Bên cạnh đó, tôi nghĩ rằng bạn có thể bị thiếu điểm .. – nfechner

+1

Java rõ ràng đã phạm sai lầm ở đây. Họ nên có được chính xác hơn trong khi diễn viên im lặng được cho phép. Và lý do cho rễ đúc trong một quyết định tồi tệ khác. Thông số kỹ thuật về hoạt động loại tích phân là một mớ hỗn độn hôi thối. – irreputable

Trả lời

28

Hành vi này được xác định bởi ngôn ngữ (và do đó là OK). Từ the JLS:

15.26.2 Các nhà khai thác Compound Assignment

Một biểu thức phân công hợp chất có dạng E1 op = E2 tương đương để E1 = (T) ((E1) op (E2)) , trong đó T là loại E1, ngoại trừ E1 chỉ được đánh giá một lần. Ví dụ, đoạn mã sau là đúng:

short x = 3; 
x += 4.6; 

và kết quả trong x có giá trị 7 vì nó tương đương với:

short x = 3; 
x = (short)(x + 4.6); 
+4

Đây là một cái gì đó thường là quá nhìn, chúng ta có xu hướng nghĩ rằng + = chỉ là một phiên bản ngắn hơn để viết, nhưng nó có ý nghĩa khác. Mẹo hay để nhớ. – Ewald

+0

không ổn. java là sai. không có lý do nào ví dụ nên biên dịch. – irreputable

+4

@irreputable - tốt, đó là một cái gì đó để mất đến với các nhà thiết kế ngôn ngữ; trình biên dịch phù hợp với đặc điểm kỹ thuật. – McDowell

5

Nó biên dịch bởi vì trình biên dịch được chuyển đổi

sum += 0.56787; 

để

sum = (int)(sum + 0.56787); 
+1

Bạn có thể cung cấp liên kết tới tài liệu, giải thích hành vi này không. Tôi nghĩ rằng hành vi bình thường là tự động chuyển đổi thành một loại có độ chính xác cao hơn. –

+1

Dàn diễn viên được thực hiện sau khi bổ sung, không phải trước đó. Xem câu trả lời hàng đầu. –

3

này không có gì để làm với kiểu mạnh nhưng chỉ với các quy tắc khác nhau cho các chuyển đổi ngầm.

Bạn đang xem hai toán tử khác nhau tại đây. Trong trường hợp đầu tiên, bạn có toán tử gán đơn giản "=" không cho phép gán double cho một số int. Trong trường hợp thứ hai, bạn có toán tử gán "+ =" cho phép thêm double vào một số int bằng cách chuyển đổi double thành một số int trước tiên.

+0

Có, nhưng điều này rất khác với cách mọi thứ hoạt động trong C++ hoặc C#. –

+0

Chắc chắn, đây là những quy tắc cụ thể cho Java từ JLS. –

+1

Eh? Sự lựa chọn các quy tắc cho chuyển đổi ngầm, theo định nghĩa, là tất cả về cách gõ mạnh so với yếu. –