Java中的布尔值与布尔值
Posted
技术标签:
【中文标题】Java中的布尔值与布尔值【英文标题】:Boolean vs boolean in Java 【发布时间】:2011-04-13 07:39:09 【问题描述】:在 Java 中围绕 Integer
与 int
进行了讨论。前者的默认值为null
,而后者的默认值为0
。 Boolean
与 boolean
怎么样?
我的应用程序中的变量可以有0
/1
值。我想使用boolean
/Boolean
,不想使用int
。我可以改用Boolean
/boolean
吗?
【问题讨论】:
出于系统设计的原因,我会选择布尔值,因为它具有“用户尚未决定”选项,它既不等于“真”,也不等于“假”。只有在我 100% 确定真/假选项足够的情况下,我才会使用布尔原语。在数据库中,NULL 选项通常可以毫无问题地使用(或者只是在以后的需求中删除 NOT NULL 限制) What's the difference between boolean and Boolean in Java? 的完全副本(因为 GWT 没有任何区别)。 【参考方案1】:是的您可以改用Boolean
/boolean
。
第一个是对象,第二个是原始类型。
第一个,你会得到更多有用的方法。
考虑到内存开销,第二个很便宜第二个会节省更多内存,所以去吧
现在选择你的方式。
【讨论】:
您可以将其表述为“第二个将为您节省更多的内存,所以去吧”。 Boolean 上有用的方法大部分都可以在没有它的实例的情况下调用。 只要你使用 Boolean.valueOf(value) 代替 new Boolean(value),内存应该不是问题。 对于AsyncTask
,您只能使用Boolean
而不是boolean
。
应该注意的是,布尔值实际上有 3 个状态...true
、false
和 null
,其中布尔值有 2 个逻辑状态(true
和 false
)
布尔值不会保护您对布尔值的任何内存。 Boolean 有两个常量实例,TRUE 和 FALSE,无论您是否使用 Boolean,它们都存在。对象内部的布尔值总是与 VM 的字长一样大,因此它通常与布尔值的引用/指针大小相同。在堆栈上可能会有所不同。但是当它被 jitted 时,可以安全地假设它具有适合 CPU 的机器字大小。但是:对于非常不同的数组!。【参考方案2】:
Boolean
包装布尔原始类型。在 JDK 5 及更高版本中,Oracle(或 Oracle 收购它们之前的 Sun)引入了 autoboxing/unboxing,它基本上允许您这样做
boolean result = Boolean.TRUE;
或
Boolean result = true;
编译器基本上是这样做的,
Boolean result = Boolean.valueOf(true);
所以,对于你的答案,是的。
【讨论】:
注意:您不能总是安全地将Boolean
分配给boolean
。如果您的Boolean
是null
,并且您尝试将其分配给boolean
,它将在运行时抛出NullPointerException
。
如果Boolean
是一个类,那么即使我将另一个类的值更改为引用同一个布尔变量的值,为什么值总是假的?这个Boolean
有什么意义,那么如果我们不能从不同的实例类引用/作为参数传递?
找到了答案,我们可以使用AtomicBoolean
并从不同的类中引用它【参考方案3】:
我有点扩展提供的答案(因为到目前为止,他们专注于自己的“自己的”/人工术语,专注于对特定语言进行编程,而不是关注创建编程语言的场景背后的大局,一般来说,即当类型安全与内存考虑因素有所不同时):
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
第 3 行 (bar)?1:0
上的 Java 代码说明 bar (boolean) 不能隐式转换(强制转换)为 int。我提出这一点并不是为了说明 JVM 背后的实现细节,而是要指出,就低级别的考虑(如内存大小)而言,人们确实必须更喜欢值而不是类型安全。特别是如果该类型安全没有像在以
如果值 \in 0,1 然后转换为布尔类型,否则抛出异常。
只是为了说明 0,1
字节不是类型或位
请注意,在内存中,0,1 范围内的变量仍将占用至少一个字节或一个字(xbits 取决于寄存器的大小),除非经过特殊处理(例如很好地打包在内存中 - 8 “布尔”位转换为 1 个字节 - 来回)。
通过更喜欢类型安全(例如将值放入/包装到特定类型的盒子中)而不是额外的值打包(例如使用位移位或算术),人们确实可以有效地选择编写更少的代码而不是获得更多的内存。 (另一方面,人们总是可以定义一个自定义用户类型,这将促进所有比布尔值不值的转换)。
关键字与类型
最后,您的问题是关于比较 keyword 与 type。我认为重要的是要解释为什么或如何通过使用/首选关键字(“标记”为primitive)而不是类型(使用另一个关键字class的普通复合用户可定义类)来获得性能 或者换句话说
boolean foo = true;
对比
Boolean foo = true;
第一个“事物”(类型)不能被扩展(子类化)并且不是没有原因的。有效地,primitive 和 wrapping 类的 Java 术语可以简单地转换为 inline 值(一个 LITERAL 或一个常量,只要编译器在可以推断替换,或者如果不是 - 仍然回退到包装值)。
因琐碎而实现优化:
“更少的运行时转换操作 => 更快的速度。”
这就是为什么当实际类型推断完成时,它可能(仍然)最终会在必要时使用所有类型信息实例化包装类(或转换/转换为此类信息)。
所以,boolean 和 Boolean 之间的区别恰恰在于 Compilation 和 Runtime(有点远但几乎就像 instanceof 与 getClass())。
最后,自动装箱比基元慢
请注意,Java 可以做到autoboxing 只是一个“语法糖”。它不会加速任何事情,只是让您编写更少的代码。而已。仍在执行类型信息容器的转换和包装。出于性能原因,请选择始终跳过使用类型信息创建类实例的额外内务处理以实现类型安全的算法。缺乏类型安全是你为获得性能付出的代价。对于具有布尔值表达式的代码,类型安全(当您编写的代码较少,因此 implicit 代码)将是至关重要的,例如用于 if-then-else 流控制。
【讨论】:
【参考方案4】:您可以使用Boolean constants - Boolean.TRUE
和Boolean.FALSE
代替0
和1
。如果原始是您所追求的,您可以创建类型为boolean
的变量。这样您就不必创建新的Boolean
对象。
【讨论】:
【参考方案5】:一个观察:(虽然这可以被认为是副作用)
boolean 作为一个基元可以说是或否。
Boolean 是一个对象(它可以表示是或否或“不知道”,即 null)
【讨论】:
【参考方案6】:基本上 boolean 表示原始数据类型,其中 Boolean 表示引用数据类型。这个故事开始于 Java 想要成为纯粹的面向对象,它提供了包装类概念来过度使用原始数据类型。
boolean b1;
Boolean b2;
b1
和 b2
不相同。
【讨论】:
【参考方案7】:您可以使用布尔值/布尔值。简单是要走的路。 如果您不需要特定的 api(Collections、Streams 等)并且您没有预见到您将需要它们 - 请使用它的原始版本(布尔值)。
使用原语可以保证不会传递空值。 您不会陷入这样的陷阱。下面的代码抛出 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;
当你需要一个对象时使用布尔值,例如:
布尔流, 可选 布尔值集合【讨论】:
【参考方案8】:Boolean
是线程安全的,因此您可以考虑这个因素以及答案中列出的所有其他因素
【讨论】:
以上是关于Java中的布尔值与布尔值的主要内容,如果未能解决你的问题,请参考以下文章