26

我的代码类似于以下内容:

public class A {
        private HashMap<Character, Boolean> myMap;

        public A() {
            myMap = new HashMap<Character, Boolean>();
            String mychars = "asdfzxcvqwer";
            for (char c : mychars.toCharArray())
                myMap.put(c, true);
        }

        public void doo(String input) {
            StringBuilder output = new StringBuilder();
            for (char c : input.toCharArray()) {
                if (myMap.get(c))
                    output.append(c);
            }
        }
        //...
        //...
    }

为什么我在该行收到空指针异常 (NPE) if (myMap.get(c))

4

9 回答 9

64

如果c不包含在 中myMap,则返回null,不能将其拆箱为boolean.

尝试 :

Boolean b = myMap.get(c);
if(b != null && b){
...
于 2012-12-03T16:19:53.590 回答
17

如果myMap不包含匹配的键c,则myMap.get(c)返回 null。在这种情况下,当 JVM 将它期望的java.lang.Boolean对象拆箱到boolean原语中以执行条件时,它会找到一个空对象并因此抛出一个java.lang.NullPointerException.

以下块等同于您在示例中的内容,应该更容易理解您为什么会有NullPointerException

if (((Boolean) myMap.get(c)).booleanValue()) 

我会将您的原始条件改写为:

if ( myMap.containsKey(c) )

我希望这有帮助。

于 2012-12-03T16:28:10.803 回答
7

改变

if ( myMap.get(c) )

if ( myMap.containsKey(c) && myMap.get(c))
于 2012-12-03T16:30:55.900 回答
3

改变这个

for ( char c : input.toCharArray() )
{
  if ( myMap.get(c) )
     output.append(c);
}

为了这

for ( char c : input.toCharArray() )
{
  if ( myMap.containsKey(c) )
     output.append(c);
}

将利用地图定义的方法来检查地图上是否注册了某个键。我将保持for原样,因为您似乎想检查一组键。

myMap.get(c)返回与该键关联的值,或者null如果该键未注册。

作为旁注,请记住,如果将此方法与自定义对象一起使用,则必须重新定义hashcodeandequals方法。

建议:我只是出于一个遥远的想法提出这个建议,如果它不是对您的代码的正确解释,请忽略它。如果您的地图仅包含一个布尔值来确定是否“包含”某个值,我强烈建议您使用 aHashSet代替,因为地图在这种情况下没有任何意义。

于 2012-12-03T16:30:19.050 回答
3

Character如果map中没有必需的实体,则map.get(key)返回null并在内部if语句中导致NullPointerException抛出。

于 2012-12-03T16:19:35.033 回答
3

黑暗中的刺伤:你的地图中是否有分配给特定角色的条目c?如果没有,Java 可能会尝试拆箱空值...

于 2012-12-03T16:22:52.163 回答
2

您的代码非常混乱。

  • do 是保留关键字,请勿将其用作方法名称。
  • 'if' 表达式必须返回一个布尔值,而不是 null。
  • myMap 的初始化写不正确

这是一个工作版本:

import java.util.HashMap;

public class A {
    private HashMap<Character, Boolean> myMap;

    public A() {
        this.myMap = new HashMap<Character, Boolean>();
        String mychars = "asdfzxcvqwer";
        for ( char c : mychars.toCharArray() )
            myMap.put(c, true);
    }

    public String execute(String input) {
        StringBuilder output = new StringBuilder();
        for ( char c : input.toCharArray() )
        {
            if ( this.myMap.get(c) != null )
                output.append(c);
        }
        return output.toString();
    }


    public static void main(String[] args) {
        A test = new A();
        test.execute("abc");
    }
}
于 2012-12-03T16:25:56.873 回答
1

或者,您可以使用apache.commons.lang3来检查Boolean和处理null检查BooleanUtils.isTrue(c)

解释:

NPE 究竟是在哪里被抛出,即何时get()在地图上被调用或何时if(...)被执行,存在一个普遍的混淆。

您的地图声明为:

myMap = new HashMap<Character, Boolean>();

其中包含一个原始boolean包装类Boolean作为映射条目的值。

当你这样做时:

if (myMap.get(c))

myMap这是一个在调用时HashMap返回,因为映射中不存在某个键。然后将其拆箱为原始状态,这就是NPE被抛出的地方,而不是当您自己调用时。nullget()nullbooleanget()

于 2020-05-05T22:29:30.757 回答
0

就我而言,我只是用一个 catch 块处理它,如下所示:

@PostMapping("/findAllLastExecutedApi")
    public ResponseEntity<Map<String,List<Results>>>findAllLastExecuted(@RequestBody Map<String,String> uuids) {
        try{ 
            // NPE is triggered here : 
            if(uuids.get("demoId").isEmpty()) {
                Map<String,List<Results>> badResults= Collections.singletonMap("Invalid demoId provided, is empty",null);
                log.error("Invalid demoId provided, is empty {}",uuids);
                return  ResponseEntity.ok(badResults);
            }

            Map<String,List<Results>> results =
                    this.service.findAll(uuids.get("demoId"));
            return ResponseEntity.ok(results);

        }catch (NullPointerException e){
            log.error("Invalid demoId provided, is null {}",uuids);
            throw new NullPointerException("Invalid demoId provided , is null");
        }
    }
于 2021-04-05T21:00:55.083 回答