跟踪NullPointerExceptions的最佳方法是什么?

时间:2013-12-10 16:03:47

标签: java nullpointerexception runtimeexception

我现在有一些这样的例外,我总是在努力解决它们,所以任何有关如何解决这些问题的指南或建议都会很好,而不必依赖其他人来帮助他们。 目前我有一个关于如何解决它的建议,我们将不胜感激,但从长远来看,一般建议如何追查问题的原因会更好。

class Egg extends Bee{
    protected void anotherDay() {

        eat();
        if(age>=3)
        {
            HashMap<String, Hive> thisHive = Garden.GARDEN.getHiveMap();
            Larvae larvae = new Larvae(this.health, this.age);
            thisHive.get("a").bees.set(thisHive.get("a").beeIndex, larvae);  //-------LINE 27
            //thisHive.get("a").replaceBee(larvae)   Line 27 was origionally this throwing the same exception

        }
        age++;
        System.out.println("Egg" + " age " + this.age + " health " + this.health);

    }
}

import java.util.ArrayList;

class Hive {
    protected int honey;
    protected int royalJelly;
    protected int pollen;
    public int beeIndex; // used to know what the index of bee you are in is
    public boolean holdAdd;
    ArrayList<Bee> bees = new ArrayList<Bee>();
    protected Hive(int honeyStart, int royalJellyStart, int pollenStart)
    {
        bees = new ArrayList<Bee>();
        this.setHoney(honeyStart);
        this.setRoyalJelly(royalJellyStart);
        this.setPollen(pollenStart);
        System.out.println("hive made");
        System.out.println(honey + " honey");
        System.out.println(royalJelly + " royalJelly");
        System.out.println(pollen + " pollen");
        holdAdd = false;
    }
    //code removed ...

    public void replaceBee(Bee addBee) {
        bees.set(beeIndex, addBee);
    }

    // code removed

    protected void anotherDay() {
        int i = 0;
        for(int k = 0; k < bees.size(); k++)
        {
            i++;
            Bee bee = bees.get(k);
            bee.anotherDay(); // ----------------LINE 144
            beeIndex = i;
        }
        // code removed 
    }
}


public class Garden {

    static HashMap<String, Hive> HiveMap = new HashMap<String, Hive>();
    public static final Garden GARDEN = new Garden();
    public static void main(String[] args) {
            GARDEN.anotherDay(); //------------------LINE 21
        }
    }

    //CODE REMOVED

    public HashMap<String, Hive> getHiveMap()
    {
        return Garden.HiveMap;
    }
    // CODE REMOVED


    protected void anotherDay() {
        //CODE REMOVED 

        //should find all Hives and call anotherday() on them each

        for(Hive currentHive : HiveMap.values()){
            currentHive.anotherDay(); //------------LINE 56
        }

        }
        //CODE REMOVED 
}

4 个答案:

答案 0 :(得分:5)

NullPointerException是代码中的一种情况,您尝试访问/修改尚未初始化的对象。

理想情况下,你不应该修复NPE,而是需要确保你没有在Null对象上操作/调用。

  • 您将获得NPE的几个场景
  • 在未初始化的对象上调用方法
  • 方法中传递的参数为null使用
  • 在一个空的对象上同步
  • Hashtable的键为null
  • 单个语句中的链式方法调用

我们如何安全处理

<强> 1。更好的编码实践

例如1:改进编码风格

String s=getValue();
// this is error prone
if(s.equals("SOMEVALUE"){
}
// Rather you can check for
if("SOMEVALLUE".equals(s)){

}

eg2:不要将Null作为返回类型从对象返回,比如说如果要返回List,而不是返回null,则可以尝试Collections.emptyList()

  public List getEmpList(){
    // some operation
     if(exp) {
       return List
     }
     else{
       return Collections.emptyList();  //dont return null
     }

   }

2.提供足够的测试覆盖率。

NPE是RunTimeException,你应该能够从测试类中捕获大部分RTE。

第3。不鼓励传递空参数

但有些地方你必须支持NPE

  有效的java中的Joshua bloch说:“可以说,一切都是错误的   方法调用归结为非法论证或非法状态,   但其他例外标准用于某些类型的非法行为   论点和状态。如果调用者在某个参数中传递null   约定禁止哪些空值   抛出NullPointerException而不是IllegalArgumentException。“

答案 1 :(得分:4)

如果你有堆栈跟踪,通常可以通过一些练习轻松发现NullPointerExceptions:它来自调用方法或引用对象为null的属性。因此,请查看报告的行并查看正在引用的对象。在您的示例中:

thisHive.get("a").bees.set(thisHive.get("a").beeIndex, larvae);

thisHive可以为空吗? get("a")返回什么?可以为空吗? (是的,因为如果找不到密钥,映射将返回null)。 bees可以为空吗?等等。您可以经常发现它只是查看代码,但调试器使它更容易。在该行上设置断点并查看什么是null。然后向后工作以理解它为何为空。

要注意的一件事是autoboxing:如果你有一个声明为包装类的变量(LongIntegerBoolean等),你可以将其引用为原始的,你会得到一个NPE:

private int getMyInt() {
   Integer myInt = null;
   return myInt;
}

private void doSomething() {
   int i = getMyInt();
}

答案 2 :(得分:1)

您可以在调试器中为NPE设置断点,因此当它们出现时会始终停止显示堆栈帧内容(涉及的字段和对象)。以下是如何使用Idea实现的目标:

enter image description here

enter image description here

答案 3 :(得分:0)

我的建议是保持简短的行,不要进行太多嵌套的内联调用。如果您在如下所示的行中出现错误,则很难确定哪个对象为null。

thisHive.get("a").bees.set(thisHive.get("a").beeIndex, larvae) .