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

[Java原始碼]Boolean

因為業務發展關係,前段時間將一個風控平臺從Ruby語言遷移到了Java平臺,基於Spring進行了重構,寫了一段時間Java後,自己發現竟然還挺喜歡的(可能因為那段時間真的深深體會了 動態語言一時爽,重構火葬場 的玩笑)。所以後續決定閱讀部分原始碼進行深入提升Java水平,網上搜索了一番,看到了很多的推薦,例如Spring框架的原始碼之類的,還有一些其他的開源元件專案,但是後面想想還是先從Java基礎入手吧,於是就有了這篇文章,從最簡單的Boolean開始。

原始碼基於 jdk1.8.0_181.jdk 版本。水平有限,第一次看相關程式碼,也第一次寫?如有建議和意見,歡迎聯絡指出。

概要

Java的Boolean

物件是對boolean基本資料型別的封裝,有著一個欄位存放對應的boolean資料值,提供了許多方法方便對boolean進行操作。

類定義

public final class Boolean implements java.io.Serializable,Comparable<Boolean>
複製程式碼

因為帶有final關鍵字,也就是不可繼承,另外實現了SerializableComparable介面,也就是可以進行序列化和比較的。

屬性

public static final Boolean TRUE = new Boolean(true);

public static
final Boolean FALSE = new Boolean(false); 複製程式碼

TRUEFALSE定義了兩個靜態常量,代表著boolean中的truefalse

@SuppressWarnings("unchecked")
public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");
複製程式碼

獲取類資訊,Boolean.TYPE == boolean.class兩者是等價的。

private final boolean
value; 複製程式碼

Boolean因為是boolean的包裝類,所以這裡就是包含了對應的boolean基本型別的變數

private static final long serialVersionUID = -3665804199014368530L;
複製程式碼

方法

構造方法

 public Boolean(boolean value) {
    this.value = value;
 }

public Boolean(String s) {
    this(parseBoolean(s));
}
複製程式碼

存在兩個構造方法,一個是傳入boolean型別值,一個是傳入字串解析,而對應的解析方法如下:

public static boolean parseBoolean(String s) {
    return ((s != null) && s.equalsIgnoreCase("true"));
}
複製程式碼

這裡就很直白的告訴了你,只有true(忽略大小寫)格式的字串才會返回true,其餘的都為false。這裡自己因此還踩過坑,一直以為字串存在時就是真值,還是和Ruby不一樣的。

valueOf 方法

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

public static Boolean valueOf(String s) {
    return parseBoolean(s) ? TRUE : FALSE;
}
複製程式碼

我們通過Boolean b = new Boolean(true);時會獲得一個新的例項物件,當你並不需要這個新例項而只要對應的值時,就應該採用這裡的靜態方法,直接返回了上面定義的靜態變數,節省了一點記憶體又避免了建立一個新例項的時間開銷。

booleanValue 方法

public boolean booleanValue() {
    return value;
}
複製程式碼

獲取對應的boolean型別值。

toString 方法

public static String toString(boolean b) {
    return b ? "true" : "false";
}

public String toString() {
    return value ? "true" : "false";
}
複製程式碼

返回對應布林值的String物件。如果為true則返回"true"字串,否則就是"false"。

hashcode 方法

@Override
public int hashCode() {
  	return Boolean.hashCode(value);
}

public static int hashCode(boolean value) {
  	return value ? 1231 : 1237;
}
複製程式碼

其中重寫了hashcode方法,返回值呼叫了靜態方法hashcode,而靜態方法返回值:當true時返回1231,false返回1237。這裡很有意思的是這兩個固定的數字,很好奇為什麼是這兩個值,所以網上搜索了下,有兩篇回答可以參考一下。

  1. Boolean.hashCode()

  2. Why does Java's Boolean.hashCode() map the values 'true' and 'false' to 1237 and 1231 instead of 1 and 0?

大致意思是,主要這兩個是較大的質數(實際上其他較大的質數也可以),至於較大質數的原因是可以有效減少Hash碰撞衝突的發生。而Boolean是一個很常用的物件,會經常在其他裡面使用,這麼做有助於提升效率。

equals 方法

public boolean equals(Object obj) {
	  if (obj instanceof Boolean) {
  	  	return value == ((Boolean)obj).booleanValue();
  	}
  	return false;
}
複製程式碼

首先判斷傳入的obj是不是Boolean的例項,然後比較兩者的值是否相等。從這裡可以發現,如果我們習慣於在判斷前增加if (null == obj)的邏輯,其實在這裡是可以忽略的,因為null肯定不是Boolean的例項,會直接返回false

getBoolean 方法

public static boolean getBoolean(String name) {
    boolean result = false;
    try {
      	result = parseBoolean(System.getProperty(name));
    } catch (IllegalArgumentException | NullPointerException e) {
    }
    return result;
}
複製程式碼

從程式碼上看,這個方法並不是將輸入字串轉換成boolean型別的方法。而是當且僅當 系統屬性 中存在著對應名稱的屬性,且它的值為“true”(忽略大小寫)時,返回true型別,否則返回false

compare 方法

public int compareTo(Boolean b) {
  	return compare(this.value,b.value);
}

public static int compare(boolean x,boolean y) {
  	return (x == y) ? 0 : (x ? 1 : -1);
}
複製程式碼

比較兩個Boolean例項物件或者boolean型別值,當相等時,返回0;否則根據第一個值進行判斷,第一個值為true時返回1,否則返回-1。

logical 比較方法

public static boolean logicalAnd(boolean a,boolean b) {
		return a && b;
}

public static boolean logicalOr(boolean a,boolean b) {
    return a || b;
}


public static boolean logicalXor(boolean a,boolean b) {
  return a ^ b;
}
複製程式碼

提供了三個靜態方法,對於兩個boolean型別值進行與、或、異或操作,返回對應的判斷結果值。

boolean型別

在看程式碼的過程中,想知道boolean到底是個啥東西,然後去看了下 oracle 的官方檔案,突然學到了一點小知識,順帶記錄一下。

在Java的八種基本資料型別中,除了boolean其它7種都有明確的位元組數長度,只有boolean沒有給出具體的位元組數長度定義,詳細的介紹如下:

boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information,but its "size" isn't something that's precisely defined.

boolean只存在truefalse兩個值,這個資料型別也是用於跟蹤真/假條件的簡單標誌。這個資料型別代表了1bit的資訊,但是它的大小並沒有明確的定義。由此搜尋了一下,發現具體的應該是由Java虛擬機器器規範定義的。官方的檔案 Java Virtual Machine Specification 有這個相關的說明,boolean型別值會被編譯使用int型別進行替換,也就是4位元組的大小;而boolean型別陣列,jvm並不是直接支援的,而是通過byte[]實現,其中也就是佔用1位元組。具體的說明可以檢視提供的原文連結,也是非常有意思的資訊。

總結

整體的原始碼是很簡單的,但是這次檢視原始碼的過程中也學到了很多的東西,平時一些可能完全不會關注的點,在這次過程中也都學習到了,例如有些情況下應該使用Boolean.valueOf(true)替換new Boolean(true)hashCode的值,boolean的相關檔案定義等等,魔鬼藏在細節裡,繼續加油。

最後

對應部落格地址:blog.renyijiu.com/post/java原始碼…