java.lang -> Boolean
java.lang -> Boolean
是什么
Boolean 类是将 boolean 基本类型进行包装。类型为 Boolean 的对象包含一个单一属性 value,其类型为 boolean。
此外还提供了许多将 boolean 转换为 String、String 转换为 boolean,以及其他一些方法。
构造器
有两个构造器
public Class Boolean {
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");
private final boolean value;
public Boolean(boolean value) {
this.value = value;
}
public Boolean(String s) {
this(parseBoolean(s));
}
}
我们可以看到在内部维护了一个 boolean 类型的 value,在我们调用构造器的时候会将 value 给赋值。
还可以看到内部还有三个常量其中两个是 TRUE、FALSE 分别代表布尔值的两个状态,这样我们在使用的时候就可以直接用而不需要去构建一个。
还有一个 TYPE 是接收了 Class.getPrimitiveClass("boolean"); 的返回值,我们跟进去可以看到 getPrimitiveClass 是一个 native 方法。
static native Class<?> getPrimitiveClass(String name);
我们直接查看 openJDK 中对应的 Class.c 文件可以发现对应的方法 Java_java_lang_Class_getPrimitiveClass
JNIEXPORT jclass JNICALL
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;
}
我们可以看到 JVM 会根据我们传递的 "boolean" name 字符串来调用 JVM_FindPrimitiveClass 来获取到 jclass,返回到 java 层则为 Class
并且如果常量 TYPE 在执行到 toString() 时还是会调用到 native 方法。如下
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
public String getName() {
String name = this.name;
if (name == null)
// 会调用到 getName0();
this.name = name = getName0();
return name;
}
private native String getName0();
我们会发现最终会调用到 getName0() 这个 native 方法。所以我们继续去看 C 文件
static JNINativeMethod methods[] = {
{"getName0", "()" STR, (void *)&JVM_GetClassName},
{"getSuperclass", "()" CLS, NULL},
{"getInterfaces0", "()[" CLS, (void *)&JVM_GetClassInterfaces},
{"getClassLoader0", "()" JCL, (void *)&JVM_GetClassLoader},
{"isInterface", "()Z", (void *)&JVM_IsInterface},
{"getSigners", "()[" OBJ, (void *)&JVM_GetClassSigners},
{"setSigners", "([" OBJ ")V", (void *)&JVM_SetClassSigners},
{"isArray", "()Z", (void *)&JVM_IsArrayClass},
{"isPrimitive", "()Z", (void *)&JVM_IsPrimitiveClass},
{"getComponentType", "()" CLS, (void *)&JVM_GetComponentType},
{"getModifiers", "()I", (void *)&JVM_GetClassModifiers},
{"getDeclaredFields0","(Z)[" FLD, (void *)&JVM_GetClassDeclaredFields},
{"getDeclaredMethods0","(Z)[" MHD, (void *)&JVM_GetClassDeclaredMethods},
{"getDeclaredConstructors0","(Z)[" CTR, (void *)&JVM_GetClassDeclaredConstructors},
{"getProtectionDomain0", "()" PD, (void *)&JVM_GetProtectionDomain},
{"getDeclaredClasses0", "()[" CLS, (void *)&JVM_GetDeclaredClasses},
{"getDeclaringClass0", "()" CLS, (void *)&JVM_GetDeclaringClass},
{"getGenericSignature0", "()" STR, (void *)&JVM_GetClassSignature},
{"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations},
{"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool},
{"desiredAssertionStatus0","("CLS")Z",(void *)&JVM_DesiredAssertionStatus},
{"getEnclosingMethod0", "()[" OBJ, (void *)&JVM_GetEnclosingMethodInfo},
{"getRawTypeAnnotations", "()" BA, (void *)&JVM_GetClassTypeAnnotations},
};
我们可以看到这个数组的第一行 getName0 就被定义为了 JVM_GetClassName 的函数。大家还记得当时 Object 文章里类似的地方吗,是的没错 Class 类中也有 registerNatives 的本地方法来注册对应的方法。
public final class Class<T> implements java.io.Serializable,GenericDeclaration,Type,
AnnotatedElement {
private static native void registerNatives();
static {
registerNatives();
}
}
好了我们继续来看 getName0 被定义为对应的 JVM_GetClassName 函数后。最终的 JVM_GetClassName 实现函数是下面展示的.
JVM_ENTRY(jstring, JVM_GetClassName(JNIEnv *env, jclass cls))
assert (cls != NULL, "illegal class");
JVMWrapper("JVM_GetClassName");
JvmtiVMObjectAllocEventCollector oam;
ResourceMark rm(THREAD);
const char* name;
if (java_lang_Class::is_primitive(JNIHandles::resolve(cls))) {
// 注意这一行函数里会去 type2name_tab 数组里去寻找
name = type2name(java_lang_Class::primitive_type(JNIHandles::resolve(cls)));
} else {
// Consider caching interned string in Klass
Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls));
assert(k->is_klass(), "just checking");
name = k->external_name();
}
oop result = StringTable::intern((char*) name, CHECK_NULL);
return (jstring) JNIHandles::make_local(env, result);
JVM_END
我们可以看到第八行会去调用 type2name 函数,最终根据一个数组获得对应的名称,比如这里下标为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*"
};
重要方法
parseBoolean
public static boolean parseBoolean(String s) {
// 判断参数 s 是否不为空并且是 "true" 字符串
return ((s != null) && s.equalsIgnoreCase("true"));
}
valueOf
public static Boolean valueOf(boolean b) {
// 三目表达式没什么好说的
return (b ? TRUE : FALSE);
}
toString
public static String toString(boolean b) {
// 三目表达式没什么好说的
return b ? "true" : "false";
}
public String toString() {
return value ? "true" : "false";
}
hashCode
public static int hashCode(boolean value) {
// 即 true 返回 1231 而 false 返回 1237
return value ? 1231 : 1237;
}
equals
public boolean equals(Object obj) {
// 方法就是先判断是不是从 Boolean 实例化出来的,然后再继续比较是不是相等。
if (obj instanceof Boolean) {
return value == ((Boolean)obj).booleanValue();
}
return false;
}
getBoolean
public static boolean getBoolean(String name) {
boolean result = false;
try {
// 从系统环境中获取指定 name 如果失败则返回 false
result = parseBoolean(System.getProperty(name));
} catch (IllegalArgumentException | NullPointerException e) {
}
return result;
}
compareTo
public int compareTo(Boolean b) {
return compare(this.value, b.value);
}
public static int compare(boolean x, boolean y) {
// 如果 boolean 相等则返回 0 否则 x 为真返回 1 为假返回 -1
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;
}
上面三个方法也没啥好说的大家自己看。