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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

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 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,
不知道我的答案是不是正解,大家讨论

回复 使用道具 举报
txl 中级黑马 2013-1-21 13:44:14
43#
本帖最后由 黑马唐贤来 于 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
{

}
求解释


回复 使用道具 举报
这两句出错的原理跟上面的一样,都是将null跟整数计算时出错,而不是往集合存放的时候出错
回复 使用道具 举报
本帖最后由 张向辉 于 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
回复 使用道具 举报
黑马张英涛 发表于 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
分析的不错
首先判断外层的三元运算符,map.get(str)==null为真,于是该表达式的值为i,既然已经有值了为 ...

说了啊,是因为表达式3改了i的值,如果表达式3跟 i 无关 jvm是不会管表达式3是什么值的吧, 我测试了下直接给他传了个5/0都没错。至于他内部的机理就要聆听高见了
回复 使用道具 举报
黑马张英涛 发表于 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 14:06
表达式1 ? 表达式2 : 表达式3

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

恩,其实我内心深处也有这么个疑问。。
你还是公布答案吧
回复 使用道具 举报
123
您需要登录后才可以回帖 登录 | 加入黑马