阅读更多

5顶
5踩

编程语言

转载新闻 你真的会用Java中的三目运算符吗?

2015-10-27 10:02 by 副主编 mengyidan1988 评论(7) 有10497人浏览
写在前面:
引用

三目运算符是我们经常在代码中使用的,a= (b==null?0:1); 这样一行代码可以代替一个 if-else,可以使代码变得清爽易读。但是,三目运算符也是有一定的语言规范的。在运用不恰当的时候会导致意想不到的问题。前段时间遇到(一个由于使用三目运算符导致的问题,其实是因为有三目运算符和自动拆箱同时使用(虽然自动拆箱不是我主动用的)。

一、三目运算符

对于条件表达式b?x:y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值。一个条件表达式从不会既计算x,又计算y。条件运算符是右结合的,也就是说,从右向左分组计算。例如,a?b:c?d:e将按a?b:(c?d:e)执行。

二、自动装箱与自动拆箱

基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。 一般我们要创建一个类的对象实例的时候,我们会这样: Class a = new Class(parameters); 当我们创建一个Integer对象时,却可以这样: Integer i = 100;(注意:和 int i = 100;是有区别的 ) 实际上,执行上面那句代码的时候,系统为我们执行了: Integer i = Integer.valueOf(100); 这里暂且不讨论这个原理是怎么实现的(何时拆箱、何时装箱),也略过普通数据类型和对象类型的区别。我们可以理解为,当我们自己写的代码符合装(拆)箱规范的时候,编译器就会自动帮我们拆(装)箱。那么,这种不被程序员控制的自动拆(装)箱会不会存在什么问题呢?

三、问题回顾

首先,通过你已有的经验看一下下面这段代码。如果你得到的结果和后文分析的结果一致(并且你知道原理),那么请忽略本文。如果不一致,请跟我探索下去。
Map<String,Boolean> map =  new HashMap<String, Boolean>();
Boolean b = (map!=null ? map.get("test") : false);

以上这段代码,是我们在不注意的情况下有可能经常会写的一类代码(在很多时候我们都爱使用三目运算符)。当然,这段代码是存在问题的,执行该代码,会报NPE.
Exception in thread "main" java.lang.NullPointerException

首先可以明确的是,既然报了空指针,那么一定是有些地方调用了一个null的对象的某些方法。在这短短的两行代码中,看上去只有一处方法调用map.get("test"),但是我们也都是知道,map已经事先初始化过了,不会是Null,那么到底是哪里有空指针呢。我们接下来反编译一下该代码。看看我们写的代码在经过编译器处理之后变成了什么样。

反编译后代码如下:
HashMap hashmap = new HashMap();
Boolean boolean1 = Boolean.valueOf(hashmap == null ? false : ((Boolean)hashmap.get("test")).booleanValue());

看完这段反编译之后的代码之后,经过分析我们大概可以知道问题出在哪里。((Boolean)hashmap.get("test")).booleanValue()的执行过程及结果如下:
引用

hashmap.get(“test”)->null;

(Boolean)null->null;

null.booleanValue()->报错

好,问题终于定位到了。那么接下来看看如何解决该问题以及为什么会出现这种问题。

四、原理分析

通过查看反编译之后的代码,我们准确的定位到了问题,分析之后我们可以得出这样的结论:NPE的原因应该是三目运算符和自动拆箱导致了空指针异常。

那么,这段代码为什么会自动拆箱呢?这其实是三目运算符的语法规范。参见jls-15.25,摘要如下:
引用

If the second and third operands have the same type (which may be the null type), then that is the type of the conditional expression.

If one of the second and third operands is of primitive type T, and the type of the other is the result of applying boxing conversion (§5.1.7) to T, then the type of the conditional expression is T.

If one of the second and third operands is of the null type and the type of the other is a reference type, then the type of the conditional expression is that reference type.

简单的来说就是:当第二,第三位操作数分别为基本类型和对象时,其中的对象就会拆箱为基本类型进行操作。

所以,结果就是:由于使用了三目运算符,并且第二、第三位操作数分别是基本类型和对象。所以对对象进行拆箱操作,由于该对象为null,所以在拆箱过程中调用null.booleanValue()的时候就报了NPE。

五、问题解决

如果代码这么写,就不会报错:
Map<String,Boolean> map =  new HashMap<String, Boolean>();
Boolean b = (map!=null ? map.get("test") : new Boolean(false));

就是保证了三目运算符的第二第三位操作数都为对象类型。

这和三目运算符有关。

本文转自:伯乐在线 - HollisChuang
来自: 伯乐在线
5
5
评论 共 7 条 请登录后发表评论
7 楼 qq4628241 2015-11-03 13:41
正解
6 楼 QQ973446095 2015-10-30 08:18
很详细的分析
5 楼 maochong2009 2015-10-29 13:47
Boolean b = (map!=null&&map.get("test")!=null ? map.get("test") : false);  这样不就可以了嘛 ,这个问题的根源在于 null被强转 false 本来就不对~
4 楼 whlt20090509 2015-10-28 14:22
经验就是这样不断积累的,赞一个
3 楼 norce 2015-10-27 17:02
写的好详细,表示长知识了
2 楼 yipsilon 2015-10-27 12:05
尽量使用 Boolean.FALSE,而不是 new 一个新的。
1 楼 mangguo 2015-10-27 11:09

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java三目运算符 效率_你真的了解Java中的三目运算符吗?

    三目运算符是我们经常在代码中使用的,a= (b==null?0:1);这样一行代码可以代替一个if-else,可以使代码变得清爽易读。但是,三目运算符也是有一定的语言规范的。在运用不恰当的时候会导致意想不到的问题。本文就介绍...

  • java四目运算符_你真的会用 Java 中的三目运算符吗?

    写在前面:三目运算符是我们经常在代码中使用的,a= (b==null?0:1);这样一行代码可以代替一个if-else,可以使代码变得清爽易读。但是,三目运算符也是有一定的语言规范的。在运用不恰当的时候会导致意想不到的问题。...

  • 什么是三目运算符?三目运算符怎么使用?

    三目运算符又称为“三元运算符”和“条件运算符”,在java、C、C++、python、JavaScript、PHP等编程语言中都有三目运算符。三目运算符的作用就是判断,可以理解为if条件判断的简化版。

  • Java中的三目运算符

    Java中的三目运算符

  • java中三目运算符详解

    对于有些选择分支结构,可以使用简单的条件运算符来代替. 如: if(a&lt;b) min=a; else min=b; 可以用下面的条件运算符来处理 min=(a&lt;b)?a:b;  其中"(a&lt;b)?a:b"是一个"条件表达式",它是这样执行的: ...

  • Java程序员们真的了解三目运算符吗?还有这些你意想不到的问题,怎么解决?

    三目运算符是我们经常在代码中使用的,a= (b==null?0:1);这样一行代码可以代替一个if-else,可以使代码变得清爽易读。但是,三目运算符也是有一定的语言规范的。在运用不恰当的时候会导致意想不到的问题。 一、三目...

  • Java中的运算符--三目运算符

    Java的三目运算符 -result = ? : ;-

  • Java 三目运算符

    Java是一种广泛使用的编程语言,具有强大的功能和丰富的语法结构,其中三目运算符是Java语言中的一个重要概念。其中,“boolean-expression”是一个布尔表达式,如果它的结果为true,则返回“expression1”,否则...

  • java 三目运算符

    Java基础

  • 你真的会用三目运算符吗?

    写在前面: 三目运算符是我们经常在代码中使用的,a=...前段时间遇到(一个由于使用三目运算符导致的问题,其实是因为有三目运算符和自动拆箱同时使用(虽然自动拆箱不是我主动用的)。 一、三目运算符 对

  • java中三步表达式,Java中三目运算符之类型转换

    前言相信各位 Javaer 对于三目运算符(三元运算符)都不陌生,较多情况下使用三目运算符即可节省一个 if-else 语句赋值的编写,笔者也是经常使用三目运算符,前段时间遇到了一点三目运算符的类型转换的坑,便在此记录...

  • Java中三目运算符出现空指针异常

    三目运算符在我们日常的开发中使用的也是非常的多,那么针对于三目运算符发现了如下空指针问题

  • Java三目运算符boolean?condition1:condition2的使用及类型转换

    三目运算符&lt;表达式1&gt;?&lt;表达式2&gt;:&lt;表达式3&gt;...以上是三目运算符的基本定义与使用。表面上看来,应该是比较简单。在《Java程序员面试宝典》这本书里,我们见到了了两道比较有意思的题...

  • JAVA 系列——三目运算符

    条件运算符,是一个程序开发的术语,优先级高于,低于其他。适用于程序开发。

  • JAVA 中三目运算符空指针

    开发过程中遇到一个问题,顺手记录一下。场景如下: public class PriceVO { private Double originalPrice; private Double preferentialPrice; public Double getOriginalPrice() {return originalPrice;} ...

  • Java三目运算符

    Java三目运算符

  • 华中科技大学电信专业 课程资料 作业 代码 实验报告-数据结构-内含源码和说明书.zip

    华中科技大学电信专业 课程资料 作业 代码 实验报告-数据结构-内含源码和说明书.zip

  • java 游戏飞翔的小鸟

    java 制作游戏 飞翔的小鸟

  • setuptools-25.3.0.zip

    Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。

Global site tag (gtag.js) - Google Analytics