簡體   English   中英

在Java中將字節轉換為int的最優雅方式

[英]Most elegant way to convert a byte to an int in 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);

所以我們從255的整數值開始,將其轉換為一個字節(變為-1),然后使用魔術公式將其轉換回int。 預期的產出是:

255
-1
255

我想知道這個a & 0xff是否是進行此轉換的最優雅方式。 checkstyle例如抱怨在這個地方使用一個幻數,並且忽略這個檢查的值不是一個好主意,因為在其他地方255可能真的是一個應該避免的幻數。 而且我自己為這樣的東西定義常量非常煩人。 所以我想知道JRE中是否有一種標准方法來代替這種轉換? 或者可能是已定義的具有最高無符號字節值的常量(類似於Byte.MAX_VALUE,這是最高有符號值)

所以要保持簡短的問題:如何在不使用幻數的情況下將字節轉換為int?

好的,到目前為止提到了以下可能性:

  • 繼續使用& 0xff並忽略checkstyle中的幻數255。 缺點:其他可能在某些其他范圍(不是位操作)中使用此數字的地方也不會被檢查。 優點:簡單易讀。
  • 為它定義我自己的常量,然后使用像& SomeConsts.MAX_UNSIGNED_BYTE_VALUE這樣的代碼。 缺點:如果我需要在不同的類中,那么我必須為這個darn常量定義我自己的常量類。 優勢:這里沒有神奇的數字。
  • 做一些聰明的數學,比如b & ((1 << Byte.SIZE) - 1) 編譯器輸出很可能是相同的,因為它被優化為常量值。 缺點:代碼相當多,難以閱讀。 優點:只要1未被定義為幻數(checkstyle默認忽略它),我們這里沒有幻數,我們不需要定義自定義常量。 當字節有一天被重新定義為16位(開玩笑)時它仍然有效,因為Byte.SIZE將是16而不是8。

還有更多想法嗎? 也許其他一些聰明的逐位操作比上面的那個短,只使用0和1之類的數字?

進行轉換的標准方法。 如果你想擺脫checkstyle投訴,嘗試定義一個常量,它可以幫助:

 public final static int MASK = 0xff;

順便說一句 - 請記住,它仍然是自定義轉換。 byte是一個signed數據類型,因此一個byte永遠不能保存255 字節可以存儲位模式1111 1111但是這表示整數值-1

所以實際上你正在做位操作 - 位操作總是需要一些神奇的數字。


BTW-2:是的,有一個Byte.MAX_VALUE常量,但這是 - 因為byte是有符號的 - 定義為2 7 -1(= 127)。 所以它對你的情況沒有幫助。 -1需要一個字節常量。

忽略checkstyle。 0xFF 不是幻數。 如果為它定義一個常量,則常量一個魔術常量,這比0xFF本身更難理解。 在最近幾個世紀接受教育的每個程序員都應該比他的女朋友更熟悉0xFF ,如果有的話。

我們應該寫這樣的代碼嗎?

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

我為此寫了一個方法

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

這也是short和int參數的重載(其中int擴展為long)。

您可以使用Byte.MAX_VALUE + Byte.MAX_VALUE + 1來保持FindBug關閉,而不是0xFF,但我認為這是一個混淆。 並且它很容易弄錯(先前的版本)。

Java 8提供了Byte.toUnsignedIntByte.toUnsignedLong (可能用於非常大的字節)方法:

byte b = (byte)255;
int c = Byte.toUnsignedInt(b); // 255
long asLong = Byte.toUnsignedLong(b); // 255

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM