JDK源码解读(第二弹:Boolean)
我们知道有个基本类型叫boolean,它的值只有两种,true或者false。Boolean类正是对基本类型boolean进行了封装,提供了一些常用的方法。
看源码之前建议先看一下API文档,或者边看源码边看API,这样可以更好的理解。可以直接去看官方的API文档,也可以看我的上一篇文章,是对API文档的翻译,连接如下:https://blog.csdn.net/lianjiww/article/details/82230178
源码很容易获取,大家都知道怎么看,但是考虑到手头不方便打开IDE的同学以及为了方便对照阅读,这里先贴上源码:
package java.lang;
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
{
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
@SuppressWarnings("unchecked")
public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");
private final boolean value;
private static final long serialVersionUID = -3665804199014368530L;
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(parseBoolean(s));
}
public static boolean parseBoolean(String s) {
return ((s != null) && s.equalsIgnoreCase("true"));
}
public boolean booleanValue() {
return value;
}
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public static Boolean valueOf(String s) {
return parseBoolean(s) ? TRUE : FALSE;
}
public static String toString(boolean b) {
return b ? "true" : "false";
}
public String toString() {
return value ? "true" : "false";
}
@Override
public int hashCode() {
return Boolean.hashCode(value);
}
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
public boolean equals(Object obj) {
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
public static boolean getBoolean(String name) {
boolean result = false;
try {
result = parseBoolean(System.getProperty(name));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}
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);
}
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;
}
}
以上源码我把注释全都去掉了,因为这些注释就是API文档的内容,对于API,上一篇文章中已经进行过了翻译,所以这里就直接来看源码了。
API中说了,Boolean是对基本类型boolean的封装,那么必然要有一个变量用来保存boolean的值,这个变量就是的value,代码如下: private final boolean value;
注意它是final的,不可变。
他有两个构造函数:
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(parseBoolean(s));
}
可分别传入boolean和String类型。但是要注意,对于String类型,当传入的字符串等于”true”(不分大小写)时判断为true,否则为false。这是通过parseBoolean实现的:
public static boolean parseBoolean(String s) {
return ((s != null) && s.equalsIgnoreCase("true"));
}
但是实际使用的时候,API文档中明确说明并不推荐使用构造函数,而是推荐使用静态工厂valueOf方法。方法源码如下:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
public static Boolean valueOf(String s) {
return parseBoolean(s) ? TRUE : FALSE;
}
但是这和使用构造函数又有什么区别?
我们知道boolean和其他对象不同,它只有两种值,要么是true,要么是false。那么作为一个boolean的封装对象,Boolean类在全局只需要有两个实例即可,一个代表true,一个代表false。这两个对象就是:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
如果使用构造函数创建出更多的对象,无非还是true或false,只是耗费了更多的空间和性能,没什么大用 。
所以如果需要一个true,一般不用new Boolean(true)
,而是使用Boolean.valueOf(true)
或Boolean.valueOf("true")
,或者直接使用Boolean.TRUE
,这样不会有新的对象产生。
在这里我们先不继续往下看源码,停下来想一想,上面Boolean的这两个静态变量其实体现了一种非常好的设计思想。
如果我们的一个类只允许有少量的几种值,那就可以用几个static final的变量来表示这几个实例,而不用每次都new一个新的对象出来。
比如一周只可能有7天,那如果我们有一个Weekday的类,可以在Weekday里来一个static final的MONDAY属性, 想得到一个周一的实例,只要使用Weekday.MONDAY即可,而不用new一个新的对象出来。
甚至可以取消public的构造方法,只提供静态工厂方法,这样就强制使用静态属性或静态工厂方法,而无法使用构造函数来new一个新的对象。这样还有一个好处就是,因为实例就只有固定的那几个,所以equal方法可以直接用 ==来判断,超级简单。
接着往下看源码,hashcode:
@Override
public int hashCode() {
return Boolean.hashCode(value);
}
public static int hashCode(boolean value) {
return value ? 1231 : 1237;
}
hashcode值也只有两种,true的时候是1231,false的时候是1237。
之前分析Object源码的时候,我们知道了hashcode是用来干嘛的。简单的说,hashCode是为了提高散列表的性能,它会决定对象在散列表中的存放位置,我们需要每个对象的hashcode尽可能的不重复。
所以true和false的hashcode就需要是两个不能太小也不能太大的质数,太小了容易重复,太大了浪费空间。1231和1237则满足这样的条件。当然了 ,这样的质数还有很多,并不是非要使用这两个质数才行,但为什么Boolean的设计者恰恰就使用了1231和1237这两个质数,估计得去问设计者本人了。
再来看equals的源码:
public boolean equals(Object obj) {
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
很简单,就是先判断是不是Boolean的实例,然后再判断值相不相等。
再来看一下比较方法:
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实现Comparable接口是为了方便在集合中进行比较,需要实现的方法就是这个compareTo。
我们注意到Boolean中还有一个静态属性TYPE
: public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");
不多说,看一下以下代码的输出就明白了:
System.out.println(Boolean.class); -- 输出class java.lang.Boolean
System.out.println(boolean.class); -- 输出boolean
System.out.println(Boolean.TYPE); -- 输出boolean
其余的几个方法,toString以及逻辑操作的几个方法都很简单,没什么好看的。
上一篇: 从 JDK 源码角度看 Boolean
下一篇: 【LeetCode题解】18.四数之和