A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 我是菜鸟 于 2013-1-21 15:37 编辑

public static void main(String[] args)
{
        Map<String, Integer> map = new HashMap<String, Integer>();
        String str = "x";
        Integer i = Math.random()*10 > 7? 5 : null;
        System.out.println(i);


        map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));
}

这段代码会报NullPointerException,看看哪位能找出来并说出原因


=============================================================================


HashMap<String, Integer>
map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));

在编译时期就要确定表达式的类型
i==null? 1 : i,表达式2和3分别是int和Integer,该语句的返回类型是int,可以推出表达式3也就是 (map.get(str) + (i==null? 1 : i))的返回类型为int
可以看作:
map.get(str)==null ? Integer : int,所以当i=5的时候,i可以正常拆箱,但当i=null,拆箱的时候调用null.intValue(),就会报空指针异常

验证:
map.put(str, map.get(str)==null ? 1 : (map.get(str) + (i==null? 1 : i)));
把i改成常量,保证表达式2类型为int,这时无论i等于什么,程序都正常,可以说明问题就出在表达式2的拆箱


所以在使用三元运算符,如果:两边表达式的类型不一致,最好做显式强制类型
map.put(str, map.get(str)==null ? i : (Integer)(map.get(str) + (i==null? 1 : i)));

*如果有问题或疑问,请指出,谢谢














点评

赶紧申请改名啊 准备申请入学测试了  发表于 2013-1-21 13:57

评分

参与人数 2技术分 +1 黑马币 +12 收起 理由
Rancho_Gump + 1 赞一个!
黄锦成 + 12 鼓励一下

查看全部评分

48 个回复

正序浏览
我是菜鸟 发表于 2013-1-21 14:06
表达式1 ? 表达式2 : 表达式3

表达式1已经为true,执行表达式2,就算表达式3如何修改表达式2的任何变 ...

恩,其实我内心深处也有这么个疑问。。
你还是公布答案吧
回复 使用道具 举报
黑马张英涛 发表于 2013-1-21 14:00
说了啊,是因为表达式3改了i的值,如果表达式3跟 i 无关 jvm是不会管表达式3是什么值的吧, 我测试了下直 ...

表达式1 ? 表达式2 : 表达式3

表达式1已经为true,执行表达式2,就算表达式3如何修改表达式2的任何变量也不会执行的

例如:
int x =1;
System.out.println(true?x:x++);
结果还是1
回复 使用道具 举报
我是菜鸟 发表于 2013-1-21 13:51
分析的不错
首先判断外层的三元运算符,map.get(str)==null为真,于是该表达式的值为i,既然已经有值了为 ...

说了啊,是因为表达式3改了i的值,如果表达式3跟 i 无关 jvm是不会管表达式3是什么值的吧, 我测试了下直接给他传了个5/0都没错。至于他内部的机理就要聆听高见了
回复 使用道具 举报
黑马张英涛 发表于 2013-1-21 13:24
public static void main(String[] args)
        {
                Map map = new HashMap();

分析的不错
首先判断外层的三元运算符,map.get(str)==null为真,于是该表达式的值为i,既然已经有值了为什么还要执行表达式3呢?
回复 使用道具 举报
本帖最后由 张向辉 于 2013-1-21 13:51 编辑
黑马张英涛 发表于 2013-1-21 13:24
public static void main(String[] args)
        {
                Map map = new HashMap();


i == null ? 1 : i   并没有修改 i 的值   整个表达式的值是1
回复 使用道具 举报
这两句出错的原理跟上面的一样,都是将null跟整数计算时出错,而不是往集合存放的时候出错
回复 使用道具 举报
txl 中级黑马 2013-1-21 13:44:14
42#
本帖最后由 黑马唐贤来 于 2013-1-21 13:53 编辑
舒远 发表于 2013-1-21 09:43
map.put(str, map.get(str) == null ? i : Integer.valueOf(map.get(str) + (i == null ? 1 : i)));
最后一 ...


     为什么下面的代码冒号两边类型不一致,依然可以呢        
                  Integer i = 0;
          System.out.print(i==1?i:"1");

还有如下代码
         

public class print {
  public static void main(String[] args)
  {
   Integer i = null;
   System.out.print(i==null?i:new test());
  }
  
}
class test
{

}
求解释


回复 使用道具 举报
本帖最后由 赵彦辉 于 2013-1-21 13:41 编辑

我测试的是这两句抛的空指针异常

  1.           public static void main(String[] args)
  2.       {
  3.               Map<String,Integer>  map = new HashMap<String,Integer>();
  4.               String str = "x";
  5. //             Integer i = Math.random()*10 > 7? 5 : null;
  6. //              System.out.println(i);
  7.               map.put(str, 5);
  8.               map.put(str,null);
  9.              map.put(str,5 + map.get(str));
  10.              map.put(str, 1 + map.get(str));
  11. //             map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));
  12.           /*
  13.             map.get(str)==null      i = 5
  14.             map.get(str) !=null      5 + map.get(str)
  15.             
  16.             map.get(str)==null      i = null
  17.             map.get(str) !=null     1 + map.get(str)
  18.             */
  19.              Set<String> keySet = map.keySet();
  20.               for(Iterator<String> it = keySet.iterator();it.hasNext();)
  21.               {
  22.                      String str1 = it.next();
  23.                      System.out.println(str1);
  24.                      System.out.println(map.get(str));
  25.               }
  26.       }
复制代码
map.put(str,5 + map.get(str));
map.put(str, 1 + map.get(str));
请看这两句代码:map.get(str) != null, 那么键所对应的值就为 5 + map.get(str)或者 1 + map.get(str)
我测试的时候就只有这两句抛空指针异常,这个时候具体的键对应的值往Map集合中存放的时候会出错,注释掉这两句程序就OK,
不知道我的答案是不是正解,大家讨论

回复 使用道具 举报
public static void main(String[] args)
        {
                Map<String, Integer> map = new HashMap<String, Integer>();
                String str = "x";
                Integer i = Math.random()*10 > 7? 5 : null;
                System.out.println(i);
     标记: map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));
        }

分析下流程吧:
i=5的话,没问题,不考虑,关键是i=null的时候。
i=null的时候,标记前面的代码没问题,现在执行标记处的代码,首先判断外层的三元运算符,
map.get(str)==null为真,于是该表达式的值为i,但是i的值被该三元运算符的表达式3给修改了,
于是要得到i的值,jvm只能执行表达式3,运行map.get(str),结果为null,这时候jvm并不会报异常,
还要继续运算里面的三元运算符的值,求出i=1,也没问题,然后要计算null+1的值,这时候jvm根据
map的定义的类型得出null+1的值应该是Integer类型,于是会尝试将null解包成int类型进行运算,
这里有可能调用的是null.intValue()方法,但是null里面根本没有这个方法,这时候空指针异常出现了。

这应该就是问题的位置和原因了吧。




回复 使用道具 举报
太热闹了 哇唔   这样的问题 以后我必须加分!
回复 使用道具 举报
舒远 发表于 2013-1-21 12:28
i == null ? 1 : i
这个表达式的类型是int,因为i为null,返回的是1,默认int,这里没有自动装箱的机制。 ...

按你说这个表达式的类型是int,因为i为null,返回的是1,默认int,不要忘记了前面还有一个表达式map.get(str),最后的结果是null+1,null需要拆箱,也会报错的
对于整个表达式,map.put(str, map.get(str) == null ? i : (map.get(str) + (i == null ? 1 : i)));表达式3( (map.get(str) + (i == null ? 1 : i)))是执行不到的

有其他人已经在提问这问题了 关于关于三元运算符
回复 使用道具 举报
本帖最后由 方寅生 于 2013-1-21 13:06 编辑

map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));
这一句之前加一句
i=i==null? 1 : i;
然后map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));;改成
map.put(str, map.get(str)==null ? i : (map.get(str) + i));
回复 使用道具 举报
舒远 黑马帝 2013-1-21 12:50:35
36#
张向辉 发表于 2013-1-21 12:41
远哥 说的有道理   对于他这道题来说想深了   我测试了他的程序  在 i  不等于null 的情况下不会出异常
...

你还是没理解:
map.put(str,null);这句话不会报错的。
回复 使用道具 举报
舒远 发表于 2013-1-21 12:28
i == null ? 1 : i
这个表达式的类型是int,因为i为null,返回的是1,默认int,这里没有自动装箱的机制。 ...

远哥 说的有道理   对于他这道题来说想深了   我测试了他的程序  在 i  不等于null 的情况下不会出异常
问题就出在这
map.put(str, map.get(str)==null ? i : (map.get(str) + (i==null? 1 : i)));
map.get(str)==null  为ture
第一个表达式是 i
第二个表达式也可能出错,不重要了,不执行
i 为 null 就空指针异常了  
这是简单点的考虑
回复 使用道具 举报
舒远 黑马帝 2013-1-21 12:28:36
34#
我是菜鸟 发表于 2013-1-21 12:19

也可以如下:
map.put(str, map.get(str) == null ? i : (Integer)(map.get(str) + (i == null ? 1 :  ...

i == null ? 1 : i
这个表达式的类型是int,因为i为null,返回的是1,默认int,这里没有自动装箱的机制。
回复 使用道具 举报
舒远 黑马帝 2013-1-21 12:27:17
33#
张向辉 发表于 2013-1-21 12:24
楼主貌似知道正解哎 上面有人提到问题所在了,楼主没有采纳啊
问题就出在三元运算符里 i  变量 i 指向了nul ...

问题根本不在这。。多写点代码测试一下就知道了
回复 使用道具 举报
张向辉 发表于 2013-1-21 12:19
貌似楼主知道正解哎,  我看上面有人回答到点了,楼主没有采纳哎
问题是三元运算符里的 i  指向了NULL造成 ...

呵呵~~~
大多数都知道i=null或者map.get(str)=null,但为什么会报空指针异常,这没说出来,刚看到有一个说出来了
回复 使用道具 举报
楼主貌似知道正解哎 上面有人提到问题所在了,楼主没有采纳啊
问题就出在三元运算符里 i  变量 i 指向了null
Integer i = null ;
true ? i : 其他值;  此时会报空指针异常
回复 使用道具 举报
舒远 发表于 2013-1-21 09:43
map.put(str, map.get(str) == null ? i : Integer.valueOf(map.get(str) + (i == null ? 1 : i)));
最后一 ...


也可以如下:
map.put(str, map.get(str) == null ? i : (Integer)(map.get(str) + (i == null ? 1 : i)));

再问:
(map.get(str) + (i == null ? 1 : i)),这个表达式为什么返回类型是int,分析一下
回复 使用道具 举报
貌似楼主知道正解哎,  我看上面有人回答到点了,楼主没有采纳哎
问题是三元运算符里的 i  指向了NULL造成的
Integer i = null;
true ? i : 其他值;  这样就出现空指针异常。
回复 使用道具 举报
123下一页
您需要登录后才可以回帖 登录 | 加入黑马