1

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)
Ashot Karakhanyan
  • 2,804
  • 3
  • 23
  • 28
Cdog101
  • 100
  • 1
  • 9
  • And where do you think you initialize `nums`? – Kevin Apr 30 '14 at 02:49
  • But nums needs to be formatted to the array from the client, which may have a variety of elements – Cdog101 Apr 30 '14 at 02:50
  • @Cdog101 Which line is "IntegerArray.java:37" ? –  Apr 30 '14 at 02:53
  • private final int TOTALNUMS = nums.length; – Cdog101 Apr 30 '14 at 02:55
  • So that's what I thought. You can't do this before your num is not initialized, " private final int TOTALNUMS = nums.length; ". Put the assignment in the constructor. –  Apr 30 '14 at 02:58
  • I tried, after which resulted in an error saying: IntegerArray.java:48: error: variable TOTALNUMS might not have been initialized – Cdog101 Apr 30 '14 at 03:02
  • This is when it was trying to create the evens array – Cdog101 Apr 30 '14 at 03:02
  • So basically you will have to put the variable deceleration TOTALNUMS outside the constructor and do the assignment inside the constructor and this applies to every variable decelerations+assignments that you have done. –  Apr 30 '14 at 03:05

4 Answers4

1

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.

Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
1

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.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

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.

Community
  • 1
  • 1
codenheim
  • 20,467
  • 1
  • 59
  • 80
  • If you look though most of the code depends on nums.length. is there a way around this? – Cdog101 Apr 30 '14 at 02:55
  • Yes, make sure that any code that depends on nums.length is called after the object is completely constructed, or at minimum, after the line in the constructor where you assign "nums = array". – codenheim Apr 30 '14 at 02:57
  • Consider changing TOTALNUMS from a field to a getTotalNums() method, same for the other fields, and moving the calls to main(). – codenheim Apr 30 '14 at 02:58