Question

I've had a few of these exceptions now and I’m always struggling to solve them so any guides or advice on how to fix them would be great instead of having to rely on others to help with them so much. Currently I have one advice on how to fix it would be appreciated but also advice in general on how to track down the cause of the problems would be better in the long run.

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 
}
Was it helpful?

Solution 2

If you have the stacktrace, NullPointerExceptions are usually easy to spot with a bit of practice: It comes from calling a method or referencing an property on an object that is null. So look at the line that is reported and see what objects are being referenced. In your example:

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

Can thisHive be null? what does get("a") return? Can it be null? (yes it can because a map returns null if the key is not found). Can bees be null? Etc. You can often spot it just looking at the code, but a debugger makes it even easier. Set a breakpoint on the line and see what is null. Then work backwards to understand why it is null.

One thing to be aware of is autoboxing: if you have a variable declared as a wrapper class (Long,Integer, Boolean, etc.) and you reference it as a primitive, you will get a NPE:

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

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

OTHER TIPS

NullPointerException is a situation in code where you try to access/ modify an object which has not been initialized yet.

So ideally you should not fix the NPE, rather need to make sure you are not operating/invoking on Null object.

  • Few scenarios you would get NPE
  • Invoking methods on an object which is not initialized
  • Parameters passed in a method are null Using
  • synchronized on an object which is null
  • Key to Hashtable is null
  • Chained method invocation in a single statement

How do we handle safely

1. Better coding practise

eg 1: improving coding style

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

}

eg2: Don't return Null as return type from object, say if you want to return List, and instead of return null, you can try Collections.emptyList()

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

   }

2.Provide enough test coverage.

NPE is RunTimeException, you should be able to catch most of the RTE from the test classes.

3. Discourage Passing of Null Parameters

But there are some places you must support NPE

Joshua bloch in effective java says that “Arguably, all erroneous method invocations boil down to an illegal argument or illegal state, but other exceptions are standardly used for certain kinds of illegal arguments and states. If a caller passes null in some parameter for which null values are prohibited, convention dictates that NullPointerException be thrown rather than IllegalArgumentException.”

You could set a break point for the NPE in your debugger, so it would always stop when they occur showing you the stack frame content (fields and objects involved). Here's how you can do it with Idea:

enter image description here

enter image description here

My advice is to keep lines short and don't make too many nested inline call. If you get error in a line like the following it will be hard to figure out what object was null.

thisHive.get("a").bees.set(thisHive.get("a").beeIndex, larvae) .
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top