1. 程式人生 > 程式設計 >[Java原始碼]Byte

[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原始碼…