首页天道酬勤除了博客还有哪里可以写文章(大家都在哪里写博客)

除了博客还有哪里可以写文章(大家都在哪里写博客)

admin 12-01 00:51 313次浏览

作者l霍利斯来源l霍利斯(ID: Hollis Chuang)

近日,阿里巴巴Java开发手册发布了最新版本,泰山版,这是一个不错的名字,其他的山都显得小矮人在天底下.

据说新版增加了30个法度,我还没来得及仔细看,但有粉丝告诉我,他之前在我的博客里看到过其中一个法度。

仔细看,这个问题真的很久以前就发生在我身上了,而且记录在我的博客里。

最先遇到这个问题的是我的同事。他在代码中使用了三元运算符,当代码在线运行时,NPE出现了。经过调查发现,三元运算符与自动反汇编框之间存在一定的关系,导致指针为空。

本文于2015年首次发表,目前已被1w阅读。

利用最新开发手册中提到的这一点,我翻出了上一篇文章的内容,重新整理了一下,带大家回顾一下这个知识点。

条件表达式b的

一、三目运算符

?X:y,先算条件B,再判断。如果B的值为真,则计算X的值,结果为X的值;否则,计算Y的值,结果就是Y的值.条件表达式从不同时计算X和y。条件运算符是右关联的,也就是说,它们是从右向左分组的。例如,a?b:c?D:e会按A吗?b:(c?D:e)。

00-1010自J2SE 5.0以来,已提供基本数据类型的自动拆箱和拆箱。

通常,当我们想要创建一个类的对象实例时,我们会这样做:类a=新类(参数);

当我们创建一个Integer对象时,我们可以这样做:Integer i=100(注:且int i=100有区别)

其实上面的代码执行的时候,系统是为我们执行的:Integer I=Integer . value of(100);

暂时不讨论这个原理是如何实现的(什么时候解包,什么时候打包),也跳过普通数据类型和对象类型的区别。

我们可以理解,当自己编写的代码符合开箱规范时,编译器会自动为我们开箱(拆箱)。

那么,这个不受程序员控制的自动拆包(装)盒会有什么问题吗?

00-1010首先,根据您现有的经验来看下面的代码:

MapString,Booleanmap=newHashMapString,Boolean();

Booleanb=(地图!=null?map . get(“test”): false);上面的代码是一种我们可能经常不注意就编写的代码(很多情况下,我们都喜欢使用三元运算符)。当然,这段代码有问题。如果这个代码被执行,它将被报告给NPE。

线程“main”Java . lang . nullpointerexception中出现异常

首先,可以明确的是,因为报告了空指针,所以空对象的一些方法必须在某个地方调用。

在这短短的两行代码中,似乎只有一个方法可以调用map.get('test '),但是我们都知道map已经提前初始化了,不会为Null,那么空指针在哪里呢?

接下来让我们对代码进行反编译。让我们看看我们写的代码经过编译器处理后会变成什么样。

反编译代码如下:

hashmap=new hashmap();

booleanboolean 1=boolean . value of(hashmap==null?false:((布尔)hashmap.get('test ')。booleanVaLue());看完这段反编译代码,通过分析大概就能知道问题出在哪里了。

((布尔)hashmap.get ('test '))。布尔值()的执行过程和结果如下:

hashmap . get(' test ')-null;

(布尔值)空-空;

null.booleanValue

()->报错

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

四、原理分析

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

根据规定,三目运算符的第二、第三位操作数的返回值类型应该是一样的,这样才能当把一个三目运算符的结果赋值给一个变量。

如:Person i = a>b ? i1:i2; ,就要求i1和i2的类型都必须是Person才行。

因为Java中存在一种特殊的情况,那就是基本数据类型和包装数据类型可以通过自动拆装箱的方式互相转换。即可以定义int i = new Integer(10);也可以定义Integer i= 10;

那如果,三目运算符的第二位和第三位的操作数的类型分别是基本数据类型和包装类型对象时,就需要有一方需要进行自动拆装箱。

那到底如何做的呢,根据三目运算符的语法规范。参见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") : Boolean.FALSE);

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

这和三目运算符有关。

请勿随意操作由UK8S创建的资源go如何实现Redis读写分离GoogleMap使Flutter崩溃创建实例 云内存 UMem Redis请尽node_modules/@angular/cdk/table“'没有导出的成员'CdkTextColumn'雷士灯具管理系统
java map初始化(java年终总结) 字典用的是什么数据结构(java语言程序设计与数据结构)
相关内容