Java HashMap调用方法抛出NullPointerException问题排查求助
先看你提供的代码:
private HashMap<String, HashMap<String, Integer>> attributesCountPerCategory; private HashMap<String, Integer> attributesCount; public void increaseAttributes(String attr, String category){ HashMap<String, Integer> attributes = this.attributesCountPerCategory.get(category); if (attributes == null) { this.attributesCountPerCategory.put(category, new HashMap<String, Integer>()); attributes = this.attributesCountPerCategory.get(category); } Integer c = attributes.get(attr); if(c == null){ attributes.put(attr, 0); c = attributes.get(attr); } attributes.put(attr,c++); Integer c2 = this.attributesCount.get(attr); if(c2 == null){ this.attributesCount.put(attr,0); c2 = this.attributesCount.get(attr); } this.attributesCount.put(attr,c2++); }
你提到明明做了空值检查,却在HashMap<String, Integer> attributes = this.attributesCountPerCategory.get(category);这一行抛出NPE,最可能的原因有两个:
外层HashMap
attributesCountPerCategory未初始化:你只是在类里声明了这个变量,但没有在构造函数、初始化块或者类加载阶段给它分配实例(比如没写attributesCountPerCategory = new HashMap<>();)。当你调用get(category)方法时,this.attributesCountPerCategory本身是null,调用null对象的方法自然会抛出NPE——你检查的是get()返回的attributes是否为null,却没检查外层的map本身是否存在!同样的问题也可能出现在attributesCount上,如果它也没初始化,后面调用this.attributesCount.get(attr)时也会触发NPE。多线程环境下的并发修改:如果这段代码在多线程环境中运行,有可能在你执行方法的间隙,另一个线程把
attributesCountPerCategory设置为了null,或者对它进行了其他破坏状态的操作。不过这种情况比第一种少见得多,大多数时候都是第一个原因导致的。
另外顺便提个小bug:你代码里的c++和c2++是后置自增操作,这会导致你把原来的数值put回去,而不是自增后的数值。比如c原本是0,attributes.put(attr,c++)会把0存进去,然后c才变成1,这和你想要的“计数加1”逻辑不符。应该改成attributes.put(attr, c + 1)或者attributes.put(attr, ++c)。
内容的提问来源于stack exchange,提问作者Jim Benson

