Domanda

I'm getting a NullPointerException, it seems the program can't find nums (the array)

The Class:

/**
 *Author: Chris Cherian
 *Date: 4/30/14
 *Desc: This program organizes numbers into 3 arrays - Even, Odd, and Negative.
 */
public class IntegerArray
{
    /**
     *The array that holds all the numbers.    
     */
    int nums [];

    /**
     *Holds count of the odds.
     */
    private int oddCount = 0;

    /**
     *The numbers in the array.
     */
    private int length;

    /**
     *Holds count of the positives.
     */
    private int posCount;


    public IntegerArray(int[] array)
    {
        nums = array;
    }

    /**
     *The nuber of elements in the array.
     */
    private final int TOTALNUMS = nums.length;

    /**
     *The array that holds all the even numbers.    
     */
    private int[] evens = new int[TOTALNUMS - this.getOddCount()];

    /**
     *The array that holds all the odd numbers.
     */
    private int[] odds = new int[this.getOddCount()];

    /**
     *The array that holds all the negative numbers.
     */
    private int[] negs = new int[TOTALNUMS - this.getPosCount()];

    int evenCounter = 0;

    /**
     *Gathers the total number of odds
     *@return The number of odd numbers
     */
    public int getOddCount()
    {
        for(int i = 0; i <= TOTALNUMS; i++)
        {
            if(nums[i]%2 != 0)
            {
                oddCount++;
            }
        }
        return oddCount;
    }

    /**
     *Gathers number of positives
     *@return posCount The number of positive numbers
     */
    public int getPosCount()
    {
        for(int i = 0; i <= TOTALNUMS; i++)
        {
            if(nums[i] > 0)
            {
                posCount++;
            }
        }

        return posCount;
    }
    public int[] organizeEvens()
    {
        for(int i = 0; i < nums.length; i++)
        {
            if(nums[i]%2 == 0)
            {
                evens[evenCounter] = nums[i];
                evenCounter++;
            }
        }
        return evens;
    }

    int oddCounter = 0;
    public int[] organizeOdds()
    {
        for(int i = 0; i < nums.length; i++)
        {
            if(nums[i]%2 != 0)
            {
                odds[evenCounter] = nums[i];
                oddCounter++;
            }
        }
        return odds;
    }

    int negCounter = 0;

    public int[] organizeNegs()
    {
        for(int i = 0; i < nums.length; i++)
        {
            if(nums[i]%2 == 0)
            {
                negs[negCounter] = nums[i];
                negCounter++;
            }
        }
        return negs;
    }
}

The Client:

import java.util.Scanner;

public class IntegerArrayClient
{
    public static void main(String[] jackofspades)
    {
        Die die1 = new Die(200);
        Scanner keyboard = new Scanner(System.in);

        System.out.println("How many numbers would you like to organize?");
        int numbers = keyboard.nextInt();

        int[] numbersarray = new int[numbers];

        for(int i = 0; i < numbers; i++)
        {
            numbersarray[i] = (die1.Roll() - 200);
        }

        IntegerArray numholder = new IntegerArray(numbersarray);

        int evenCount = (numbersarray.length - numholder.getOddCount());

        for(int i = 0; i < evenCount; i++)
        {
            System.out.println(numholder.organizeEvens() + "\t");
        }

    }
}

The error message I get:

Exception in thread "main" java.lang.NullPointerException
    at IntegerArray.<init>(IntegerArray.java:37)
    at IntegerArrayClient.main(IntegerArrayClient.java:20)
È stato utile?

Soluzione

The problem is that your code has an assumption that

private final int TOTALNUMS = nums.length;    

would execute after the constructor, because textually it follows it. That is an incorrect assumption - this line executes before the constructor, at the time nums is still null. This is what is causing the exception.

To fix this problem, move the initialization of TOTALNUMS into the constructor:

private final int TOTALNUMS; // It's OK to leave it final - you are allowed to set it in the constructor
...
public IntegerArray(int[] array) {
    nums = array;
    TOTALNUMS = nums.length; // If nums is set to a non-null array, this would not cause an exception
}

Finally, note that there is little point in keeping a separate final variable for the length of nums, because its length is always available to you, and you do not need to "synchronize" the two if you decide to set nums to a different array later on.

Altri suggerimenti

This peice of code

private final int TOTALNUMS = nums.length; 

is happening before nums has been initialized, it is still int nums []; - it has no size.

I assume that line 37 is this one:

   private final int TOTALNUMS = nums.length;

The problem is that nums has not been initialized at that point, and it therefore still has its default initial value. Therefore, executing num.length throws an NPE.

How so?

Well you are initializing nums in the constructor. Bur the code in the constructor body is only executed AFTER the initializers for the instance variables have all been executed.

You need to initialize TOTALNUMS, evens, odds and so on in the constructor, since they all depend on the value passed in the constructor's array parameter.

You need to lookup up member initializers and when they run in relation to the constructor. They run before the constructor. Only after that (during the constructor) are you initializing num, and that is after you've tried to use num.Length.

Move the code that depends on nums.length to the constructor, after you've assigned nums, or in a method that is called after the object is fully created (ie. don't to it in the constructor at all, add another method on the class that returns the length).

Trying to do too much in the initializers is causing trouble.

See the first answer in this question:

Java Static Initialization Order

Or the Java rules on initialization order:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2

All these lines of code are wrong because these lines are executed as the object is created, prior to the constructor that initializes nums.

  private final int TOTALNUMS = nums.length;    
  private int[] evens = new int[TOTALNUMS - this.getOddCount()];
  private int[] odds = new int[this.getOddCount()];
  private int[] negs = new int[TOTALNUMS - this.getPosCount()];

I suggest converting "evens" to "getEvens()" and calling getEvens() from main, not from the initializer. Same for each of the other fields, convert to methods that are called later.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top