Java中的Boolean与boolean有何区别?

260
在Java中,有关Integerint的讨论。前者的默认值是null,而后者的默认值是0。那么,在Booleanboolean之间呢?
在我的应用程序中,一个变量可以具有0/1的值。我想使用boolean/Boolean,而不是使用int。我能使用Boolean/boolean吗?

7
出于系统设计原因,我会选择布尔类型,因为它有一个选项“用户尚未决定”,既不等于“true”也不等于“false”。只有在我确定真/假两个选项足够时,才会仅使用布尔原始类型。在数据库中,通常可以轻松使用NULL选项(或者在需要时仅需删除NOT NULL限制)。 - CsBalazsHungary
2
准确复制自Java中boolean和Boolean有什么区别?(因为GWT没有区分)。 - Dan Dascalescu
8个回答

367

是的,你可以使用Boolean/boolean代替。

第一个是对象,第二个是原始类型。

  • 在第一个上,你会得到更多有用的方法。

  • 考虑到内存开销,第二个更加便宜。第二个将为您节省更多的内存,所以采用它吧。

现在选择你的方式吧。


77
你可以把它说成“第二种方法可以节省更多内存,所以选择它”。Boolean类的有用方法大多数都可以在没有实例的情况下调用。 - DJClayworth
3
只要您使用 Boolean.valueOf(value) 而不是 new Boolean(value),内存就不应该成为问题。 - Greg Case
3
对于 AsyncTask,你只能使用 Boolean 而不能使用 boolean - Raptor
162
需要翻译的内容:It should be noted the a Boolean actually has 3 states... true, false and null where a boolean has the logical 2 states (true and false)布尔类型实际上有三种状态,即truefalsenull,而逻辑上布尔类型只有两种状态,即truefalse - respectTheCode
4
布尔值和布尔类型并不会比Boolean节省内存。Boolean有两个常量实例:TRUE和FALSE,无论你是否使用Boolean类型,它们都存在。对象内部的布尔值大小始终与VM的字长相同,因此通常与指向Boolean的引用/指针大小相同。在堆栈上可能会有所不同。但是,在进行JIT编译时,可以安全地假定其具有适合CPU的机器字长大小。但是:对于数组来说情况就非常不同! - Angel O'Sphere
显示剩余2条评论

63

Boolean 包装了布尔原始类型。在JDK 5及以上版本中,Oracle(或被Oracle收购之前的Sun)引入了自动装箱/拆箱,这使您可以轻松地执行此操作。

boolean result = Boolean.TRUE;
或者
Boolean result = true; 

这本质上是编译器所做的事情,

Boolean result = Boolean.valueOf(true);

所以,对于你的答案,是的。


10
注意:并不总是可以安全地将 Boolean 赋值给 boolean。如果你的 Booleannull,并试图将其赋值给 boolean,则会在运行时抛出 NullPointerException - Duncan Lukkenaer
如果Boolean是一个类,为什么即使我从另一个引用同一布尔变量的类更改了值,该值始终为false?如果我们不能从不同实例类引用/传递参数,那么使用Boolean的意义何在? - user924
找到了一个答案,我们可以使用 AtomicBoolean 并从不同的类中引用它。 - user924

39

我稍微扩展一下提供的答案(因为到目前为止它们集中在自己/人工术语上,着重于编程特定语言而不是关注创建编程语言背后的更大画面,例如类型安全与内存考虑之间的区别):

int不是布尔值

考虑

    boolean bar = true;      
    System.out.printf("Bar is %b\n", bar);
    System.out.printf("Bar is %d\n", (bar)?1:0);
    int baz = 1;       
    System.out.printf("Baz is %d\n", baz);
    System.out.printf("Baz is %b\n", baz);

输出

    Bar is true
    Bar is 1
    Baz is 1
    Baz is true

第三行的Java代码(bar)?1:0说明了bar布尔类型)不能隐式转换(强制转换)为整型。我提出这个问题并不是为了说明JVM背后的实现细节,而是为了指出在低级考虑(如内存大小)方面,人们必须优先考虑值而不是类型安全。特别是如果该类型安全没有真正/完全使用,例如检查以形式进行的布尔类型中,

如果值\in {0,1},则转换为布尔类型,否则抛出异常。

只是为了说明{0,1}<{-2^31,..,2^31-1}。看起来有点过度,不是吗?在用户定义的类型中,类型安全确实非常重要,但在原始数据类型的隐式转换中并非如此(尽管后者包含在前者中)。

字节不是类型或位

请注意,在内存中,您的变量范围为{0,1}的变量仍将占用至少一个字节或一个字(xbits取决于寄存器大小),除非专门进行处理(例如,紧密地打包在内存中 - 8 "布尔"位进入1个字节 - 前后)。

通过优先考虑类型安全(例如,将值放入特定类型的“盒子”中),而不是额外的值打包(例如,使用位移或算术运算),人们实际上选择了写更少的代码而获得更多的内存。(另一方面,人们始终可以定义自定义用户类型,这将促进所有转换,不会比布尔值差)。

关键字与类型

最后,您的问题是关于比较关键字类型。我认为重要的是解释为什么或者如何通过使用/优先选择关键字(标记为原始类型)而不是类型(使用另一个关键字class定义的普通复合用户可定义类)获得性能,或者换句话说。

boolean foo = true;

对决。

Boolean foo = true;

第一个"thing"(类型)不能被扩展(子类化),这并非没有原因。在Java术语中,primitivewrapping类可以简单地翻译为inline值(直接由编译器替换的文字或常量,只要能够推断出替换,或者如果不能,则仍然回退到包装该值)。

优化是通过微不足道的方式实现的:

"更少的运行时强制转换操作=>更快的速度."

这就是为什么当实际类型推断完成后,如果需要,它可能(仍然)最终导致包装类的实例化(或转换/强制转换为这样的类)。

因此,booleanBoolean之间的区别恰好在于CompilationRuntime(有点像instanceofgetClass())。

最后,自动装箱比基本类型慢

注意Java可以进行自动装箱只是一种"语法糖"。它不会加快任何东西,只是让你写更少的代码。这就是它的全部作用。类型信息容器的转换和包装仍然会被执行。出于性能原因,选择算术运算将始终跳过创建带有类型信息的类实例的额外工作,以实现类型安全。 缺乏类型安全是您为了获得性能而付出的代价。对于具有布尔值表达式的代码,类型安全(当您编写较少且隐式代码)将非常关键,例如if-then-else流控制。


16

您可以使用布尔常量 - Boolean.TRUEBoolean.FALSE代替01。如果您需要原始数据类型,可以将变量创建为boolean类型。这样做可以避免创建新的Boolean对象。


9

一个观察:(虽然这可能被视为副作用)

boolean 是一个原始类型,只能表示是或否。

Boolean 是一个对象(它可以表示是或否,或者“不知道”,即 null)


5

基本上,布尔型代表原始数据类型,而布尔值则代表引用数据类型。这个故事始于Java想成为纯面向对象的语言,它提供了包装类的概念来克服使用原始数据类型的问题。

boolean b1;
Boolean b2;

b1b2 不相同。


2
您可以使用布尔/boolean。简单是最好的选择。如果您不需要特定的API(如Collections,Streams等),并且您没有预见到您将需要它们-请使用其原始版本(boolean)。
使用基本类型可以确保您不会传递null值。您不会陷入像这样的陷阱。下面的代码会抛出NullPointerException(来自:Booleans, conditional operators and autoboxing): public static void main(String[] args) throws Exception { Boolean b = true ? returnsNull() : false; // NPE on this line. System.out.println(b); } public static Boolean returnsNull() { return null; }
当您需要对象时,请使用Boolean,例如:
- 布尔流, - 可选项 - 布尔集合

1

Boolean 是线程安全的,因此您可以考虑将此因素与所有其他列在答案中的因素一起考虑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接