在一次采访中,我的面试官问我:
如果在以下代码中将 && 替换为 & 会出现什么问题:
String a=null; if (a!=null && a.length()>10) {...}
&&是逻辑 AND 运算符(执行短路行为,这意味着仅在需要时才评估第二个操作数)
&是按位与运算符(按位 & 运算符执行按位与运算)。
因为没有短路行为,你会得到NullPointerException.
ANullPointerException将被抛出,因为使用时没有短路&,这意味着即使左侧操作数的结果是 ,也始终false评估右侧操作数。使用时,仅当左侧操作数为 时才&&计算右侧操作数。true
第15.22.2 节。布尔逻辑运算符 &、^ 和 | 和15.23。Java 语言规范中的条件与运算符 &&描述了这种行为。
知道了 :
这里的单个 & 符号将导致NullPointerException. 因为 && 是逻辑 AND 运算符,并且仅在需要时才评估第二个操作数。
当您使用&&时,如果第一个表达式为假,它不会评估第二个表达式。 &另一方面,无论如何都会评估这两个表达式。
在您的情况下,如果您将'&&'替换为&它会抛出NullPointedException
&并且&&在表达式评估中具有不同的优先级,并且在不()包围相邻表达式的情况下,在某些情况下您可能会得到一些“惊喜”。特别是,&&在优先级中相当晚,因此您通常不需要()它,除非您将混合逻辑表达式的结果组合在一起。但&足够早让你措手不及。
&&是短路的,这意味着如果第一个表达式为假,则根本不计算第二个表达式。 &不会短路。在上面的例子中,这意味着用&&第二个表达式不会抛出 NullPointerException——这通常是&&.
与 Java 以外的类 C 语言相关:一旦您克服了上述两个陷阱,接下来就是操作实际做什么的问题。如果被评估的两个表达式都产生“布尔”结果,那么这些值将提升为 0x00 或 0x01,并且&and&&运算符将产生基本相同的答案。但是,如果其中一个表达式不是布尔值,那么您最终可能会将 0x01 和 0x02 进行与运算,例如,并产生 0x00,即使&&运算符的计算结果为真。(对于 Java 来说并不是一个特别的问题,因为它不允许 非布尔操作数&&,也不允许混合布尔/整数操作数&。)