Java 上 Boolean.booleanValue 函数的好处或用途?
Benefits or uses for the Boolean.booleanValue function on Java?
所以,我看到了这行代码:
Boolean variable = false;
/* ..stuff.. */
if(variable.booleanValue() == false) {
/* ..more stuff..*/
}
我已经完成了,在不同的地方:
Boolean variable = false;
/* ..my stuff..*/
if(!variable) {
/* ..more of my stuff..*/
}
问题是:第一段代码的 difference/advantages 是什么?
长版本是:鉴于我可以将布尔变量用作原始(布尔)变量,执行 variable.booleanValue() 甚至将其与布尔值进行比较有什么意义?如果变量未初始化,这是否也引入了空指针异常的风险(在代码上不可能,但是嘿)?
在任何情况下都建议使用 variable.booleanValue 以上 "variable"?
两个片段的行为没有区别。
At run time, unboxing conversion proceeds as follows:
If r is a reference of type Boolean, then unboxing conversion converts r into r.booleanValue()
因此 if (variable) {...}
将执行为 if (variable.booleanValue()) {...}
。因为它们是完全等价的,所以如果 variable == null
.
它们都同样容易受到 NPE 的影响
这意味着显式调用 booleanValue()
的一个可能的小优势是您可以立即看到 variable
正在被取消引用,而 variable == false
则不太明显.
是否添加 == false
或取反是个人喜好问题,我更愿意避免使用 ==
运算符将布尔表达式与 true
或 [=19= 进行比较].
但我认为更重要的是完全避免 Boolean
并尽可能使用原始类型。
我认为第一种方法相对于第二种方法的唯一优势是可以在 [=12= 之前使用旧的 JDK/Java 语言规范编译代码] 1.5
Boolean
具有三种状态 - true
、false
和 null
。如果你有未初始化的,那么在写 !var
的情况下你将得到 NullPointerException
。
还请记住,对象自动初始化为 null
而布尔原语为 false
.
区别在于自动拆箱。
第一个版本,最好编码为:
if (variable.booleanValue())
不需要 自动拆箱,因此可以与 Java.
的 1.5 之前版本一起使用
第二个版本,使用自动拆箱,因此需要1.5及以上版本。
如果您的代码需要 运行 和旧 Java 版本,您必须使用版本 1。
两者都可以抛出NPE,所以在这一点上没有区别。
points out the only thing that I can think of to technically make a difference: The second code snippet relies on Autoboxing (or rather auto-unboxing),因此,需要 Java 版本 >= 1.5。
除此之外,没有任何技术差异。你提到
Doesn't this also introduces the risk (on the code impossible, but hey) of a null pointer exception if variable is not initialized?
但是两个版本都是如此。当变量为 null
时,即使是第二个也会抛出 NullPointerException
。
不过我也对这个很好奇,做了个测试:
public class TheManyShadesOfFasle
{
public static int testBoxedBooleanBooleanValueComparison()
{
Boolean variable = false;
if(variable.booleanValue() == false)
{
return 0;
}
return 1;
}
public static int testBoxedBooleanComparison()
{
Boolean variable = false;
if(variable == Boolean.FALSE)
{
return 0;
}
return 1;
}
public static int testBoxedBooleanBooleanValueDirect()
{
Boolean variable = false;
if(!variable.booleanValue())
{
return 0;
}
return 1;
}
public static int testBoxedBooleanDirect()
{
Boolean variable = false;
if(!variable)
{
return 0;
}
return 1;
}
public static int testBooleanComparison()
{
boolean variable = false;
if(variable == false)
{
return 0;
}
return 1;
}
public static int testBooleanDirect()
{
boolean variable = false;
if(!variable)
{
return 0;
}
return 1;
}
}
可以用javap -c
反编译得到字节码:
public static int testBoxedBooleanBooleanValueComparison();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
9: ifne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBoxedBooleanComparison();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: getstatic #4 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
9: if_acmpne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBoxedBooleanBooleanValueDirect();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
9: ifne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBoxedBooleanDirect();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
9: ifne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBooleanComparison();
Code:
0: iconst_0
1: istore_0
2: iload_0
3: ifne 8
6: iconst_0
7: ireturn
8: iconst_1
9: ireturn
public static int testBooleanDirect();
Code:
0: iconst_0
1: istore_0
2: iload_0
3: ifne 8
6: iconst_0
7: ireturn
8: iconst_1
9: ireturn
并且可以看到 testBoxedBooleanBooleanValueComparison
和 testBoxedBooleanDirect
的字节码(对应你的第一和第二个代码片段)相同。 (这基本上意味着:自动拆箱是 隐式地 调用 Boolean
内部的 booleanValue
方法)。 if(!variable.booleanValue())
也一样,在testBoxedBooleanBooleanValueDirect
中可以看出。
其他案例主要是为了完整性:testBooleanComparison
和 testBooleanDirect
案例都有相同的字节码,但它与其他案例不同,因为没有发生拆箱或取消引用。
一个案例可能值得指出:将变量与 Boolean.FALSE
或 Boolean.TRUE
进行比较是有意义的,因为它隐含地涵盖了变量为 null
的情况:
if (variable == Boolean.TRUE) {
...
} else {
// Here, the variable is either "false" or "null"
}
对
if (variable == Boolean.FALSE) {
...
} else {
// Here, the variable is either "true" or "null"
}
所以,我看到了这行代码:
Boolean variable = false;
/* ..stuff.. */
if(variable.booleanValue() == false) {
/* ..more stuff..*/
}
我已经完成了,在不同的地方:
Boolean variable = false;
/* ..my stuff..*/
if(!variable) {
/* ..more of my stuff..*/
}
问题是:第一段代码的 difference/advantages 是什么?
长版本是:鉴于我可以将布尔变量用作原始(布尔)变量,执行 variable.booleanValue() 甚至将其与布尔值进行比较有什么意义?如果变量未初始化,这是否也引入了空指针异常的风险(在代码上不可能,但是嘿)?
在任何情况下都建议使用 variable.booleanValue 以上 "variable"?
两个片段的行为没有区别。
At run time, unboxing conversion proceeds as follows:
If r is a reference of type Boolean, then unboxing conversion converts r into r.booleanValue()
因此 if (variable) {...}
将执行为 if (variable.booleanValue()) {...}
。因为它们是完全等价的,所以如果 variable == null
.
这意味着显式调用 booleanValue()
的一个可能的小优势是您可以立即看到 variable
正在被取消引用,而 variable == false
则不太明显.
是否添加 == false
或取反是个人喜好问题,我更愿意避免使用 ==
运算符将布尔表达式与 true
或 [=19= 进行比较].
但我认为更重要的是完全避免 Boolean
并尽可能使用原始类型。
我认为第一种方法相对于第二种方法的唯一优势是可以在 [=12= 之前使用旧的 JDK/Java 语言规范编译代码] 1.5
Boolean
具有三种状态 - true
、false
和 null
。如果你有未初始化的,那么在写 !var
的情况下你将得到 NullPointerException
。
还请记住,对象自动初始化为 null
而布尔原语为 false
.
区别在于自动拆箱。
第一个版本,最好编码为:
if (variable.booleanValue())
不需要 自动拆箱,因此可以与 Java.
的 1.5 之前版本一起使用第二个版本,使用自动拆箱,因此需要1.5及以上版本。
如果您的代码需要 运行 和旧 Java 版本,您必须使用版本 1。
两者都可以抛出NPE,所以在这一点上没有区别。
除此之外,没有任何技术差异。你提到
Doesn't this also introduces the risk (on the code impossible, but hey) of a null pointer exception if variable is not initialized?
但是两个版本都是如此。当变量为 null
时,即使是第二个也会抛出 NullPointerException
。
不过我也对这个很好奇,做了个测试:
public class TheManyShadesOfFasle
{
public static int testBoxedBooleanBooleanValueComparison()
{
Boolean variable = false;
if(variable.booleanValue() == false)
{
return 0;
}
return 1;
}
public static int testBoxedBooleanComparison()
{
Boolean variable = false;
if(variable == Boolean.FALSE)
{
return 0;
}
return 1;
}
public static int testBoxedBooleanBooleanValueDirect()
{
Boolean variable = false;
if(!variable.booleanValue())
{
return 0;
}
return 1;
}
public static int testBoxedBooleanDirect()
{
Boolean variable = false;
if(!variable)
{
return 0;
}
return 1;
}
public static int testBooleanComparison()
{
boolean variable = false;
if(variable == false)
{
return 0;
}
return 1;
}
public static int testBooleanDirect()
{
boolean variable = false;
if(!variable)
{
return 0;
}
return 1;
}
}
可以用javap -c
反编译得到字节码:
public static int testBoxedBooleanBooleanValueComparison();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
9: ifne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBoxedBooleanComparison();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: getstatic #4 // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean;
9: if_acmpne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBoxedBooleanBooleanValueDirect();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
9: ifne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBoxedBooleanDirect();
Code:
0: iconst_0
1: invokestatic #2 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
4: astore_0
5: aload_0
6: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
9: ifne 14
12: iconst_0
13: ireturn
14: iconst_1
15: ireturn
public static int testBooleanComparison();
Code:
0: iconst_0
1: istore_0
2: iload_0
3: ifne 8
6: iconst_0
7: ireturn
8: iconst_1
9: ireturn
public static int testBooleanDirect();
Code:
0: iconst_0
1: istore_0
2: iload_0
3: ifne 8
6: iconst_0
7: ireturn
8: iconst_1
9: ireturn
并且可以看到 testBoxedBooleanBooleanValueComparison
和 testBoxedBooleanDirect
的字节码(对应你的第一和第二个代码片段)相同。 (这基本上意味着:自动拆箱是 隐式地 调用 Boolean
内部的 booleanValue
方法)。 if(!variable.booleanValue())
也一样,在testBoxedBooleanBooleanValueDirect
中可以看出。
其他案例主要是为了完整性:testBooleanComparison
和 testBooleanDirect
案例都有相同的字节码,但它与其他案例不同,因为没有发生拆箱或取消引用。
一个案例可能值得指出:将变量与 Boolean.FALSE
或 Boolean.TRUE
进行比较是有意义的,因为它隐含地涵盖了变量为 null
的情况:
if (variable == Boolean.TRUE) {
...
} else {
// Here, the variable is either "false" or "null"
}
对
if (variable == Boolean.FALSE) {
...
} else {
// Here, the variable is either "true" or "null"
}