[Java原始碼]Byte
這次我們來看看Byte
類的原始碼,基於 jdk1.8.0_181.jdk 版本 。
概要
Java的Byte
類主要是對byte
基本資料型別的封裝,有著一個欄位存放著對應的byte
資料值,另外提供了一些方法方便對byte
進行相關的操作。
類定義
public final class Byte extends Number implements Comparable<Byte>
複製程式碼
Byte
類帶有關鍵字final
,也就是不可以繼承的,另外繼承了Number
類,實現了Comparable
介面,也就是可以進行比較。
屬性
public static final byte MIN_VALUE = -128 ;
public static final byte MAX_VALUE = 127;
複製程式碼
定義了Byte
的範圍大小,由於補碼的關係,負數會比正數多一個值,MIN_VALUE
能取的值為 -2**8
,而MAX_VALUE
能取的值為2**8 - 1
,具體原碼和補碼的邏輯,可以參考下原碼、反碼、補碼的產生、應用以及優缺點有哪些? - 知乎使用者的回答 - 知乎,個人覺得講解的不錯。
public static final int SIZE = 8;
複製程式碼
定義了byte
值的二進位制補碼格式的bit
位數,固定8位。
public static final int BYTES = SIZE / Byte.SIZE;
複製程式碼
定義了byte
值的二進位制補碼格式的位元組數,計算值固定為1。
@SuppressWarnings("unchecked")
public static final Class<Byte> TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");
複製程式碼
獲取Byte
的類資訊,Byte.TYPE == byte.class
,兩者是等價的。
private final byte value;
複製程式碼
Byte
因為是byte
的包裝類,所以這裡包含了對應的byte
基本型別資料的變數。
private static final long serialVersionUID = -7183698231559129828L;
複製程式碼
內部類
private static class ByteCache {
private ByteCache(){}
static final Byte cache[] = new Byte[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Byte((byte)(i - 128));
}
}
複製程式碼
這裡定義了一個靜態的巢狀類,內部定義了一個陣列,大小為-(-128)+127+1=256
,包含了-128~127之間的值。靜態塊中初始化了陣列的值。這裡補充一個知識點,Java類的載入順序,靜態變數/程式碼塊 -> 非靜態變數/程式碼塊 -> 構造方法
,相同部分裡面是按照程式碼順序進行載入,詳細的內容可以自行搜尋學習。
關於內部類的相關說明,可以參考官方的檔案 Nested Classes 進行進一步的瞭解學習。
方法
構造方法
public Byte(byte value) {
this.value = value;
}
public Byte(String s) throws NumberFormatException {
this.value = parseByte(s,10);
}
複製程式碼
存在兩個對應的構造方法,一個傳入byte
值,一個是傳入字串解析,轉換成10進位制整數處理(注意的是這個方法可能會丟擲異常,需要注意處理),對應的解析方法下面介紹。
parseByte 方法
public static byte parseByte(String s,int radix)
throws NumberFormatException {
int i = Integer.parseInt(s,radix);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value out of range. Value:\"" + s + "\" Radix:" + radix);
return (byte)i;
}
複製程式碼
傳入字串和進位制數,呼叫了Integer.parseInt
方法獲取轉換後的整數,判斷整數範圍是否符合Byte
的範圍。如果是,強制轉換byte
型別返回;否,丟擲NumberFormatException
異常。
public static byte parseByte(String s) throws NumberFormatException {
return parseByte(s,10);
}
複製程式碼
存在一個單引數的parseByte
方法,通過呼叫上面的方法實現,預設10進位制數。
toString 方法
public static String toString(byte b) {
return Integer.toString((int)b,10);
}
public String toString() {
return Integer.toString((int)value);
}
複製程式碼
直接將byte
型別值強制轉換成int
,然後呼叫了Integer.toString
方法進行操作。
valueOf 方法
public static Byte valueOf(byte b) {
final int offset = 128;
return ByteCache.cache[(int)b + offset];
}
複製程式碼
對於byte
型別引數,直接通過計算偏移量,讀取ByteCache
內部類的靜態變數陣列對應值來操作,提升了對應的空間和時間效能。
public static Byte valueOf(String s,int radix)
throws NumberFormatException {
return valueOf(parseByte(s,radix));
}
public static Byte valueOf(String s) throws NumberFormatException {
return valueOf(s,10);
}
複製程式碼
這兩個方法是針對string
型別引數的,只是進位制設定的問題。使用parseByte
方法將字串轉換成byte
型別值,然後直接使用第一個valueOf
方法操作。
decode 方法
public static Byte decode(String nm) throws NumberFormatException {
int i = Integer.decode(nm);
if (i < MIN_VALUE || i > MAX_VALUE)
throw new NumberFormatException(
"Value " + i + " out of range from input " + nm);
return valueOf((byte)i);
}
複製程式碼
針對字串解碼,將字串轉換成Byte
型別值。主要邏輯是呼叫了Integer.decode
方法獲取解碼後的數字,然後判斷對應返回是否符合byte
要求,呼叫valueOf
返回最終結果。
除去+/-
符號,會根據實際情況進行特定的解碼,預設會處理成十進位制。0x,0X,#
開頭的會處理成16進位制,0
開頭的會處理成8進位制。
xxxValue 方法
public byte byteValue() {
return value;
}
public short shortValue() {
return (short)value;
}
public int intValue() {
return (int)value;
}
public long longValue() {
return (long)value;
}
public float floatValue() {
return (float)value;
}
public double doubleValue() {
return (double)value;
}
複製程式碼
通過強制型別轉換,擴大了原有值型別範圍,返回結果。
hashCode 方法
@Override
public int hashCode() {
return Byte.hashCode(value);
}
public static int hashCode(byte value) {
return (int)value;
}
複製程式碼
直接返回了對應的int
型別值,作為其hashCode。
equals 方法
public boolean equals(Object obj) {
if (obj instanceof Byte) {
return value == ((Byte)obj).byteValue();
}
return false;
}
複製程式碼
首先判斷傳入引數obj是不是Byte
的例項,是的話比較兩者的值是否相等;否則直接返回false
。從這裡可以看出來,我們在使用時也不需要對傳入引數進行null == obj
的判斷,可以忽略。
compare 方法
public static int compare(byte x,byte y) {
return x - y;
}
複製程式碼
比較兩者的值,x小於y時返回負數,x等於y時返回0,x大於y時返回正數。
compareTo 方法
public int compareTo(Byte anotherByte) {
return compare(this.value,anotherByte.value);
}
複製程式碼
內部呼叫compare
方法。
toUnsignedInt 方法
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
複製程式碼
將byte
轉換成無符號整數。x強制轉換成int
型別值,通過與0xff
進行位運算,保留低8位值,高24位設定成0。整體結果,0和正數保持不變,負數等於原來的值 + 2**8。
toUnsignedLong 方法
public static long toUnsignedLong(byte x) {
return ((long) x) & 0xffL;
}
複製程式碼
過程同上,只是long
為64位,低8位保持原值,高56位設定成0。
總結
通過閱讀原始碼發現,Byte
類大量使用了Integer
的方法,另外使用了內部類、位運算等方式進行了一定的邏輯優化。自己在看的過程對於內部類,補碼,類的載入順序也加深了了解,繼續加油!
最後
對應部落格地址:blog.renyijiu.com/post/java原始碼…