从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.TRUE或Boolean.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并发的原子性如何保证
从JDK源码角度看Boolean的更多相关文章
- 从JDK源码角度看Short
概况 Java的Short类主要的作用就是对基本类型short进行封装,提供了一些处理short类型的方法,比如short到String类型的转换方法或String类型到short类型的转换方法,当然 ...
- 从JDK源码角度看Byte
Java的Byte类主要的作用就是对基本类型byte进行封装,提供了一些处理byte类型的方法,比如byte到String类型的转换方法或String类型到byte类型的转换方法,当然也包含与其他类型 ...
- 从JDK源码角度看Object
Java的Object是所有其他类的父类,从继承的层次来看它就是最顶层根,所以它也是唯一一个没有父类的类.它包含了对象常用的一些方法,比如getClass.hashCode.equals.clone. ...
- 从JDK源码角度看java并发的公平性
JAVA为简化开发者开发提供了很多并发的工具,包括各种同步器,有了JDK我们只要学会简单使用类API即可.但这并不意味着不需要探索其具体的实现机制,本文从JDK源码角度简单讲讲并发时线程竞争的公平性. ...
- 从JDK源码角度看java并发的原子性如何保证
JDK源码中,在研究AQS框架时,会发现很多地方都使用了CAS操作,在并发实现中CAS操作必须具备原子性,而且是硬件级别的原子性,java被隔离在硬件之上,明显力不从心,这时为了能直接操作操作系统层面 ...
- 从JDK源码角度看线程池原理
"池"技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(SPI),具体的数据库连接实 ...
- 从 JDK 源码角度看 Object
Java的Object是所有其他类的父类,从继承的层次来看它就是最顶层根,所以它也是唯一一个没有父类的类.它包含了对象常用的一些方法,比如getClass.hashCode.equals.clone. ...
- 从JDK源码角度看并发竞争的超时
JDK中的并发框架提供的另外一个优秀机制是锁获取超时的支持,当大量线程对某一锁竞争时可能导致某些线程在很长一段时间都获取不了锁,在某些场景下可能希望如果线程在一段时间内不能成功获取锁就取消对该锁的等待 ...
- 从JDK源码角度看java并发线程的中断
线程的定义给我们提供了并发执行多个任务的方式,大多数情况下我们会让每个任务都自行执行结束,这样能保证事务的一致性,但是有时我们希望在任务执行中取消任务,使线程停止.在java中要让线程安全.快速.可靠 ...
随机推荐
- 20145314郑凯杰 《Java程序设计》实验五 实验报告
20145314郑凯杰 <Java程序设计>实验五 实验报告 实验搭档王亦徐:http://www.cnblogs.com/1152wyx/p/5471524.html 实验要求 完成实验 ...
- CSS 属性的推荐书写顺序
- bzoj 3545: [ONTAK2010]Peaks
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1124 Solved: 304[Submit][Status][Discuss] Descripti ...
- Sublime 快捷键及使用技巧
(1)打开刚刚关闭的窗口:ctrl+shift+T 默认设置. (2)全屏显示:F11 默认设置. (3)多处选择相同的词:Ctrl+D,回退选择Ctrl+U 默认设置,非常有用,可以试试. (4)取 ...
- mybatis缓存有关的设置和属性
知识点:mybatis缓存相关的设置和属性 重点:每次执行增删改操作后,一二级缓存被清空,是因为标签设置默认属性为 flushCache="true" (1) <!-- 全局 ...
- 正则表达式-RegExp-常用正则表达式
正则表达式-RegExp-常用正则表达式 作者:nuysoft/JS攻城师/高云 QQ:47214707 EMail:nuysoft@gmail.com 声明:本文为原创文章,如需转载,请注明来源 ...
- Class 的继承
简介 Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多. class Point { } class ColorPoint extends P ...
- MySQL安装的N种方式
一.二进制包安装 1.)下载:在官网的下载页面下的服务器操作系统选择 Linux- Generic : 进制分发版的格式是:mysql-<版本>-<OS>-tar.gz 2. ...
- 搭建selenium + Python环境的总结:
安装Python+Selenium 写博客是一个不错的选择,首先,是担心自己忘掉,其次,可以供大家做一个参考: 其实,这是自己第一次搭建Python环境(之前用了一周的Idle),还是比较容易的吧: ...
- torch 深度学习(3)
torch 深度学习(3) 损失函数,模型训练 前面我们已经完成对数据的预处理和模型的构建,那么接下来为了训练模型应该定义模型的损失函数,然后使用BP算法对模型参数进行调整 损失函数 Criterio ...