2011-02-02 61 views
26
đang

Ví dụ:cách thanh lịch nhất để chuyển đổi một byte đến một int trong Java

int a = 255; 
byte b = (byte) a; 
int c = b & 0xff; // Here be dragons 
System.out.println(a); 
System.out.println(b); 
System.out.println(c); 

Vì vậy, chúng ta bắt đầu với một giá trị số nguyên của 255, chuyển nó sang một byte (trở thành -1) và sau đó chuyển đổi nó trở lại đến một int bằng cách sử dụng một công thức ma thuật. Sản lượng dự kiến ​​là:

255 
-1 
255 

Tôi tự hỏi nếu điều này a & 0xff là cách thanh lịch nhất để chuyển đổi này. checkstyle ví dụ phàn nàn về việc sử dụng số ma thuật tại địa điểm này và không nên bỏ qua giá trị này cho séc này vì ở những nơi khác 255 có thể thực sự là số ma thuật cần tránh. Và nó khá khó chịu để xác định một hằng số cho những thứ như thế này một mình. Vì vậy, tôi tự hỏi nếu có một phương pháp tiêu chuẩn trong JRE mà chuyển đổi này để thay thế? Hoặc có thể là hằng số đã được xác định với giá trị byte chưa được ký cao nhất (tương tự như Byte.MAX_VALUE là giá trị được ký cao nhất)

Vì vậy, để giữ cho câu hỏi ngắn gọn: Làm thế nào tôi có thể chuyển đổi byte thành int mà không cần sử dụng số ma thuật ?

Ok, cho đến nay các khả năng sau đây được đề cập:

  • tiếp tục sử dụng & 0xff và bỏ qua những con số kỳ diệu 255 trong checkstyle. Nhược điểm: Những nơi khác có thể sử dụng số này trong một số phạm vi khác (không hoạt động bit) không được kiểm tra sau đó, quá. Ưu điểm: Ngắn và dễ đọc.
  • Xác định hằng số của riêng tôi cho nó và sau đó sử dụng mã như & SomeConsts.MAX_UNSIGNED_BYTE_VALUE. Nhược điểm: Nếu tôi cần nó trong các lớp khác nhau thì tôi phải định nghĩa lớp hằng số riêng của mình chỉ cho hằng số darn này. Ưu điểm: Không có số ma thuật ở đây.
  • Thực hiện một số phép toán thông minh như b & ((1 << Byte.SIZE) - 1). Đầu ra trình biên dịch có nhiều khả năng giống nhau vì nó được tối ưu hóa thành một giá trị không đổi. Nhược điểm: Khá nhiều mã, khó đọc. Ưu điểm: Miễn là 1 không được định nghĩa là số ma thuật (kiểu kiểm tra bỏ qua nó theo mặc định), chúng tôi không có số ma thuật ở đây và chúng tôi không cần xác định các hằng số tùy chỉnh. Và khi byte được định nghĩa lại thành 16 bit một ngày nào đó (Chỉ cần đùa) thì nó vẫn hoạt động vì sau đó Byte.SIZE sẽ là 16 và không 8.

Còn ý tưởng nào khác không? Có lẽ một số hoạt động thông minh bit-khôn ngoan mà là ngắn hơn sau đó một ở trên và chỉ sử dụng số như 0 và 1?

+0

Tôi không hoàn toàn chắc chắn những gì bạn đang thực sự cố gắng để làm ở đây, hay đúng hơn, tại sao . ** CẢNH BÁO: Không được trộn các byte và ký tự! ** Một byte chỉ có thể chứa các ký tự ASCII 7 bit * chứ không phải ký tự Java! * Ký tự Unicode rộng 21 bit, không chỉ 7 bit ** và thậm chí 15/16 bit, * * hoặc. Java nội bộ đại diện cho các ký tự dưới dạng biến rộng (tức là 1 hoặc 2) đơn vị mã UTF-16 trong hầu hết các trường hợp (* ngoại lệ: * java.unit.regex nhất thiết phải sử dụng UTF-32 cho các mẫu của nó). Bạn có thể không hợp lý mặt nạ/tiết kiệm chỉ là 7 bit đặt hàng thấp từ một số lượng 21-bit và được trái với bất cứ điều gì hợp lý và có ý nghĩa. – tchrist

+0

@tchrist: Tôi chưa từng đề cập đến các nhân vật ở đây. Nó chỉ là byte. 8 bit byte. Không nhiều không ít. – kayahr

+0

Yah, ok. Nhưng * đã ký * số lượng 8 bit. – tchrist

Trả lời

17

Điều này cách tiêu chuẩn để thực hiện chuyển đổi đó. Nếu bạn muốn loại bỏ các khiếu nại về kiểu séc, hãy thử xác định một hằng số, nó có thể giúp:

public final static int MASK = 0xff; 

BTW - hãy nhớ rằng nó vẫn là một chuyển đổi tùy chỉnh. byte là kiểu dữ liệu đã ký để một byte không bao giờ có thể giữ giá trị 255. Một byte có thể lưu trữ mẫu bit 1111 1111 nhưng giá trị này đại diện cho giá trị số nguyên -1.

Vì vậy, trên thực tế, bạn đang thực hiện các thao tác bit - và thao tác bit luôn luôn yêu cầu một số số ma thuật.


BTW-2: Vâng, có một hằng số Byte.MAX_VALUE nhưng đây là - vì byte được ký - định nghĩa là 2 -1 (= 127). Vì vậy, nó sẽ không giúp đỡ trong trường hợp của bạn. Bạn cần một hằng số byte cho -1.

+0

Có vẻ như không còn ý tưởng nào nữa. Vì vậy, tôi chấp nhận một ý tưởng có số phiếu bầu cao nhất. Cảm ơn ý kiến ​​của bạn. – kayahr

10

Bỏ qua kiểu kiểm tra. 0xFFkhông phải số ma thuật. Nếu bạn xác định một hằng số cho nó, hằng số hằng số ma thuật, điều này ít dễ hiểu hơn bản thân số 0xFF. Mỗi lập trình viên được đào tạo trong những thế kỷ gần đây nên quen thuộc hơn với 0xFF hơn với bạn gái của mình, nếu có.

chúng ta có nên viết mã như thế này không?

for(int i = Math.ZERO; ...) 
2

Tôi đã viết một phương pháp cho việc này như

public static int unsigned(byte x) { 
    return int (x & 0xFF); 
} 

mà bị quá tải cho ngắn và int thông số, quá (nơi int được mở rộng để lâu).

Thay vì 0xFF, bạn có thể sử dụng Byte.MAX_VALUE + Byte.MAX_VALUE + 1 để giữ FindBug đóng, nhưng tôi cho rằng đó là một sự che khuất. Và nó quá dễ dàng để làm cho nó sai (s. Phiên bản trước đó).

+1

Byte.MAX_VALUE + Byte.MAX_VALUE là 254 và không 255. Tôi có thể sử dụng (Byte.MAX_VALUE << 1) + 1 thay vào đó (1 đã được định nghĩa là NOT magic theo checkstyle) nhưng ... well ... No: -) – kayahr

+0

Thx cho sửa chữa, trên thực tế, một hằng số như Byte.ALL_ONES sẽ tốt đẹp. – maaartinus

+0

Còn về '(byte) (- 1)' thì sao? –

1

Java 8 cung cấp Byte.toUnsignedIntByte.toUnsignedLong (có thể cho byte thực sự lớn) phương pháp:

byte b = (byte)255; 
int c = Byte.toUnsignedInt(b); // 255 
long asLong = Byte.toUnsignedLong(b); // 255 
Các vấn đề liên quan