Java 自动装箱时的 NPE

NPE while autoboxing in Java

我有如下一段代码:

map =  db_.treeMapCreate(validMapName_)
          .keySerializer(Serializer.LONG)
          .valueSerializer(Serializer.LONG)
          .make(); //mapDB
protected void onTaskCompletion(TaskInfo task)
{
   long startBlk = task.blkId;
   long count = task.count;
   for (int i=0; i < count; ++i)
   {
      long blk = startBlk + i;
      Long oldVal = map.get(blk); //NPE here
      ...
      ...
   }
}

如何在自动装箱时获得 NPE?我可以理解在拆箱时获得 NPE,即如果我有:

long oldVal = map.get(blk)

然后可以抛出 NPE。

编辑:地图不为空。更具体地说,在 mapDB 的 BTreeMap 代码中,执行了这一行:

if(key==null) throw new NullPointerException();

万一有人想看:BtreeMap of mapDB 行:1024

部分堆栈跟踪:

java.lang.NullPointerException
        at org.mapdb.BTreeMap.get(BTreeMap.java:1024)
        at org.mapdb.BTreeMap.get(BTreeMap.java:1013)
        at com.service.onTaskCompletion(TaskHandler.java:312)

我无法重现它,所以我无法给出一个最小的、可验证的例子。 我已经尝试 运行 它以便我对不存在的密钥执行 get(),并且它不会给出 NPE。

NPE是因为map对象为null,而你指的是null的get()方法,所以NPE。 检查地图是否为 null,您会找到解决方案。

if(map!=null){
long oldVal = map.get(blk);}
 else {
System.out.println("Map is null");
}

我只看到一种可能:变量"map"为空。

您的代码示例不完整,因为您没有显示并且 "map" 真正初始化的地方。

NPE 可能是由于以下任一原因造成的:

  1. 地图为空
  2. 将空值传递给 get 方法(不是这种情况)
  3. get() 中不存在的密钥传递给 MapDB

我更关心这里的 number 3 因为,如果你传递一个不存在的键然后返回 null 并试图在 Long oldVal 中存储 null 导致异常(我相信发生以下情况):

Long l = new Long(null); //NPE

要找到一个是否是 #3,请执行以下操作

//if key don't exist MapDB returns null
if(map.get(blk) != null) { //not null } else { //yes null}

要确定 map 是否如其他人所指出的那样明显为 null,您可以按照以下步骤进行操作

//invoking get on a null can cause NPE too, so another reason
if(map != null) { // not null } else { //yes null}

为了支持 #3 可能导致 NPE 的事实,请参阅此 post 和类似的 issue

查看 BTreeMap 下面

get(Object) 的文档
public V get(Object key)
Specified by:
get in interface Map<K,V>
Overrides:
get in class AbstractMap<K,V>

查看 Map and AbstractMap get(Object key) 指定如下:

Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

get(Object) of Map<K,V> and AbstractMap<K,V> returns null 如果没有找到映射。它还能够抛出 NullPointerException。所以#3 仍然可能是这样的情况,即在映射中没有传递给 get 方法的键的条目。

我认为问题在于您查看的 BTreeMap 代码版本错误。如果回到previous commit of this class,第1024行不是:

if(key==null) throw new NullPointerException();

但是:

while(!A.isLeaf()) {...}

其中 A 设置为:

BNode A = engine.get(current, nodeSerializer);

这更有意义。基本上,null 是从 engine.get 返回的。这怎么可能超出我的理解,但这很可能是 mapdb 本身的错误。