2013-12-13 15 views
5

tôi đã viết đoạn mã sau trong Eclipse:Các toán tử bitwise trong java chỉ cho số nguyên và dài?

byte b = 10; 
/* some other operations */ 
b = ~b; 

Eclipse muốn có một dàn diễn viên để byte trong dòng của Bitwise bổ sung. Nó nói: "Loại không phù hợp: không thể chuyển đổi từ int thành byte". Tôi cũng đã thử điều này với các hoạt động bitwise khác và trên các loại tích phân khác. Đó là với ngắn và char giống nhau. Chỉ dài và số nguyên có thể sử dụng các hoạt động bitwise.

Có lý do nào cho điều này không?

+1

có thể là do máy tính phải thực hiện thao tác trên toàn bộ thanh ghi dài ít nhất 32 bit? – user2573153

+0

Vâng! Đó có thể là lý do. –

Trả lời

11

unary (như ~) và nhị phân các nhà khai thác trong chủ đề Java toán hạng của họ để "unary numeric promotion" (JLS, Section 5.6.1)"binary numeric promotion" (JLS, Section 5.6.2), tương ứng, các điều khoản lạ mắt cho "thúc đẩy điều cần ít nhất int đầu tiên".

Cụ thể, để khuyến mại số unary, trích dẫn phần JLS liên kết ở trên:

Một số nhà khai thác áp dụng chương trình khuyến mãi số unary để một toán hạng duy nhất, mà phải tạo ra một giá trị của một số loại:

... nếu toán hạng là loại byte thời gian biên dịch, ngắn hoặc char, nó được tăng giá trị kiểu int bằng cách mở rộng chuyển đổi nguyên thủy (§ 5.1.2).

(khuyến mãi số nhị phân cũng tương tự, hoạt động trên cả hai toán hạng.)

Vì vậy, ngay cả khi b là một byte, ~b là một int, bởi vì giá trị b 's được thăng lên một int đầu tiên.

Giải pháp: đúc nó trở lại một byte:

b = (byte) (~b); 

Tại sao, Java?

Điều đó để lại câu hỏi, tại sao? Có vẻ như đối với các toán tử tôi có thể tìm thấy, các hướng dẫn bytecode JVM để hoạt động trên byte s, short s và char s chỉ đơn giản là không tồn tại. Ví dụ: toán tử bổ sung bitwise unary bạn đang sử dụng (~) is implemented as an "XOR" operation with -1 (all bits set).Từ liên kết đó:

tempSpock &= ~mask; 

trở thành

25 iload_2 // Push local variable 2 (mask). 
26 iconst_m1 // Push -1. 
27 ixor // Bitwise EXCLUSIVE-OR top two ints: ~mask 

Tuy nhiên, tôi chỉ có thể find instructions for XOR (và cho các nhà khai thác unary và nhị phân khác nữa) cho int s và long s (floatdouble phiên bản tồn tại cho các nhà khai thác khác nơi thích hợp). Vì vậy, Java phải thực hiện các chương trình khuyến mãi đó vì không có hướng dẫn bytecode để thực hiện các hoạt động đó trên byte s, short s hoặc char s.

Tại sao không, JVM?

Điều đó sẽ trả về một câu hỏi khác: Tại sao JVM không hỗ trợ các lệnh bytecode như vậy? Câu trả lời dường như là, "Bởi vì sẽ có quá nhiều để mã hóa tất cả chúng trong một bộ chỉ lệnh một byte." Theo JVM Specification, Section 2.11.1,

Với Java Virtual Machine của một byte opcode kích thước, các loại mã hóa vào opcodes nơi áp lực đối với việc thiết kế tập lệnh của nó. Nếu mỗi lệnh đã nhập hỗ trợ tất cả các kiểu dữ liệu thời gian chạy của Máy ảo Java, thì sẽ có nhiều hướng dẫn hơn có thể được biểu diễn trong một byte. Thay vào đó, tập lệnh của Máy ảo Java cung cấp một mức hỗ trợ kiểu giảm cho các hoạt động nhất định. Nói cách khác, tập lệnh được cố ý không trực giao. Có thể sử dụng các hướng dẫn riêng biệt để chuyển đổi giữa các loại dữ liệu không được hỗ trợ và được hỗ trợ nếu cần.

(tôi nhấn mạnh)

Tóm lại, hướng dẫn thiết lập một bytecode của JVM ngăn cản các hướng dẫn bytecode cho hầu hết các hoạt động trên byte s, char s, và short s, cần thúc đẩy số unary và quảng bá số nhị phân .

+0

Đối số bytecode của bạn là vô nghĩa. Trình biên dịch có thể rất tốt thêm phôi nếu điều này được xác định bởi ngôn ngữ. Ví dụ, xem cách '+ =' được định nghĩa trên 'short'. – starblue

3

Có, các loại nhỏ hơn int trải qua khuyến mãi khi được sử dụng làm toán hạng cho hầu hết các toán tử. Chúng có hiệu quả được đúc thành int trước tiên. Do đó, trong mã của bạn ở trên, loại kết quả là int. Xem this section của JLS để biết chi tiết đầy đủ.

Đối với lý do tại sao Java thực hiện việc này, tôi không chắc chắn. Nhưng một lý do chính đáng là C làm điều này, và duy trì ngữ nghĩa quen thuộc có lẽ là một mục tiêu thiết kế ngôn ngữ.

Các vấn đề liên quan