因为业务发展关系,前段时间将一个风控平台从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源码…