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以及逻辑操作的几个方法都很简单,没什么好看的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值