从JDK源码角度看Boolean

Java的Boolean类主要作用就是对基本类型boolean进行封装,提供了一些处理boolean类型的方法,比如String类型和boolean类型的转换。

主要实现源码如下:

public final class Boolean implements java.io.Serializable, Comparable<Boolean> {

  private final boolean value;

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

  public static final Boolean FALSE = new Boolean(false);

  public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");

  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";
  }

  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 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;
  }
}

既然是对基本类型boolean的封装,那必然要有一个变量来保存,即value,而且它被声明为final,表明它是不可变的。两种构造函数可分别传入boolean和String类型,对于String类型会进行”to boolean”解析,即当传入的字符串忽略大小写等于”true”时判断为true,否则为false。

但是我们说一般不推荐直接用构造函数来实例化Boolean对象,这是为什么?接着往下看,对于布尔值也就只有两种状态,我们其实可以仅仅用两个对象就表示所有的布尔值,也就是说在Java的世界中只要全局存在两个Boolean对象即可,实例化出多余的Boolean对象仍然能正确表示布尔值,只是会浪费一些空间和影响时间性能。仅需要的两个对象为,

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

所以推荐的形式是Boolean.TRUEBoolean.valueOf(true)Boolean.valueOf("true"),避免生成不必要的对象。

接着再看看Boolean的TYPE属性,它toString的值其实是boolean

public static final Class<Boolean> TYPE = (Class<Boolean>) Class.getPrimitiveClass("boolean");

看看怎么来的。Class的getPrimitiveClass是一个native方法,在Class.c中有个Java_java_lang_Class_getPrimitiveClass方法与之对应,所以JVM层面会通过JVM_FindPrimitiveClass函数会根据”boolean”字符串获得jclass,最终到Java层则为Class<Boolean>

Java_java_lang_Class_getPrimitiveClass(JNIEnv *env,
                                       jclass cls,
                                       jstring name)
{
    const char *utfName;
    jclass result;

    if (name == NULL) {
        JNU_ThrowNullPointerException(env, 0);
        return NULL;
    }

    utfName = (*env)->GetStringUTFChars(env, name, 0);
    if (utfName == 0)
        return NULL;

    result = JVM_FindPrimitiveClass(env, utfName);

    (*env)->ReleaseStringUTFChars(env, name, utfName);

    return result;
}

TYPE执行toString时,逻辑如下,则其实是getName函数决定其值,getName通过native方法getName0从JVM层获取名称,

public String toString() {
        return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
            + getName();
    }

getName0根据一个数组获得对应的名称,JVM根据Java层的Class可得到对应类型的数组下标,比如这里下标为4,则名称为”boolean”。

const char* type2name_tab[T_CONFLICT+1] = {
  NULL, NULL, NULL, NULL,
  "boolean",
  "char",
  "float",
  "double",
  "byte",
  "short",
  "int",
  "long",
  "object",
  "array",
  "void",
  "*address*",
  "*narrowoop*",
  "*conflict*"
};

往下继续看HashCode,实现逻辑如下,即true返回1231而false返回1237。

public static int hashCode(boolean value) {
    return value ? 1231 : 1237;
}

equals方法就是先判断是不是从Boolean实例化出来的,然后再继续比较是不是相等。

实现Comparable<Boolean>接口是为了方便在集合中进行比较,它需要实现的方法为compareTo

此外,还提供了logicalAnd、logicalOr和logicalXor用于实现三种逻辑运算。

以下是广告相关阅读

========广告时间========

鄙人的新书《Tomcat内核设计剖析》已经在京东销售了,有需要的朋友可以到 https://item.jd.com/12185360.html 进行预定。感谢各位朋友。

=========================

相关阅读:
谈谈Java基础数据类型
从JDK源码角度看并发锁的优化
从JDK源码角度看线程的阻塞和唤醒
从JDK源码角度看并发竞争的超时
从JDK源码角度看java并发线程的中断
从JDK源码角度看Java并发的公平性
从JDK源码角度看java并发的原子性如何保证

时间: 2024-09-16 00:54:38

从JDK源码角度看Boolean的相关文章

从JDK源码角度看Float

关于IEEE 754 在看Float前需要先了解IEEE 754标准,该标准定义了浮点数的格式还有一些特殊值,它规定了计算机中二进制与十进制浮点数转换的格式及方法.规定了四种表示浮点数值的方法,单精确度(32位).双精确度(64位).延伸单精确度(43位以上)与延伸双精确度(79位以上).多数编程语言支持单精确度和双精确度,这里讨论的Float就是Java的单精确度的实现. 浮点数的表示 浮点数由三部分组成,如下图,符号位s.指数e和尾数f. 对于求值我们是有一个公式对应的,根据该公式来看会更简

从JDK源码角度看Byte

Java的Byte类主要的作用就是对基本类型byte进行封装,提供了一些处理byte类型的方法,比如byte到String类型的转换方法或String类型到byte类型的转换方法,当然也包含与其他类型之间的转换方法. 主要实现代码如下: public final class Byte extends Number implements Comparable<Byte> { public static final byte MIN_VALUE = -128; public static fina

从JDK源码角度看Long

概况 Java的Long类主要的作用就是对基本类型long进行封装,提供了一些处理long类型的方法,比如long到String类型的转换方法或String类型到long类型的转换方法,当然也包含与其他类型之间的转换方法.除此之外还有一些位相关的操作. 继承结构 --java.lang.Object --java.lang.Number --java.lang.Long 主要属性 public static final long MIN_VALUE = 0x8000000000000000L;

从JDK源码角度看Integer

概况 Java的Integer类主要的作用就是对基本类型int进行封装,提供了一些处理int类型的方法,比如int到String类型的转换方法或String类型到int类型的转换方法,当然也包含与其他类型之间的转换方法.除此之外还有一些位相关的操作. 继承结构 --java.lang.Object --java.lang.Number --java.lang.Integer 主要属性 第一部分 public static final int MIN_VALUE = 0x80000000; pub

从JDK源码角度看Short

概况 Java的Short类主要的作用就是对基本类型short进行封装,提供了一些处理short类型的方法,比如short到String类型的转换方法或String类型到short类型的转换方法,当然也包含与其他类型之间的转换方法. 继承结构 --java.lang.Object --java.lang.Number --java.lang.Short 主要属性 public static final short MIN_VALUE = -32768; public static final s

从JDK源码角度看java并发的公平性

        JAVA为简化开发者开发提供了很多并发的工具,包括各种同步器,有了JDK我们只要学会简单使用类API即可.但这并不意味着不需要探索其具体的实现机制,本文从JDK源码角度简单讲讲并发时线程竞争的公平性.         所谓公平性指所有线程对临界资源申请访问权限的成功率都一样,不会让某些线程拥有优先权.我们知道CLH Node FIFO等待队列是一个先进先出的队列,那么是否就可以说每条线程获取锁时就是公平的呢?关于公平性这里分拆成三个点分别阐述:         ① 准备入队列的节

从JDK源码角度看线程池原理

        "池"技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(SPI),具体的数据库连接实现类由不同厂商实现,数据库连接的建立和销毁都是很耗时耗资源的操作,为了查询数据库中某条记录,最原始的一个过程是建立连接.发送查询语句.返回查询结果.销毁连接,假如仅仅是一个很简单的查询语句,那么可能建立连接与销毁连接两个步骤就已经占所有资源时间消耗的绝大部分,如此低下的效率显然让人无法接受.针

从JDK源码角度看并发竞争的超时

        JDK中的并发框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待以提高性能,这时就需要用到超时机制.在JDK1.5之前并没有对此支持,当时的并发控制职能通过JVM内置的synchronized关键词实现锁,但对一些特殊要求却力不从心,例如超时取消控制.JDK1.5开始引入并发工具完美解决了此问题,JDK对并发线程开始提供超时的支持.       

从JDK源码角度看线程的阻塞和唤醒

        目前在Java语言层面能实现阻塞唤醒的方式一共有三种:suspend与resume组合.wait与notify组合.park与unpark组合.其中suspend与resume因为存在无法解决的竟态问题而被Java废弃,同样,wait与notify也存在竟态条件,wait必须在notify之前执行,假如一个线程先执行notify再执行wait将可能导致一个线程永远阻塞,如此一来,必须要提出另外一种解决方案,就是park与unpark组合,它位于JDK的juc包下,应该也是因为当时