Я получаю исключение NullPointerException, кажется, что программа не может найти nums (массив)
Класс:
/**
*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;
}
}
Клиент:
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");
}
}
}
Сообщение об ошибке, которое я получаю:
Exception in thread "main" java.lang.NullPointerException
at IntegerArray.<init>(IntegerArray.java:37)
at IntegerArrayClient.main(IntegerArrayClient.java:20)
Проблема в том, что в вашем коде есть предположение, что
private final int TOTALNUMS = nums.length;
будет выполняться после конструктора, поскольку по тексту он следует за ним. Это неверное предположение - эта строка выполняется перед конструктором, когда число nums
все равно null
. Это и вызывает исключение.
Чтобы устранить эту проблему, переместите инициализацию TOTALNUMS
в конструктор:
private final int TOTALNUMS; // It 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
}
Наконец, обратите внимание, что нет смысла указывать отдельную final
переменную для длины nums
, поскольку ее длина всегда доступна вам, и вам не нужно "синхронизировать" эти два, если вы решите установить nums
на другой массив позже.
Я предполагаю, что строка 37 является следующей:
private final int TOTALNUMS = nums.length;
Проблема в том, что nums
не была инициализирована в этой точке, и поэтому она по-прежнему имеет начальное значение по умолчанию. Поэтому выполнение num.length
вызывает NPE.
Как так?
Ну, вы инициализируете nums
в конструкторе. Bur код в теле конструктора выполняется только после того, как инициализаторы для переменных экземпляра все были выполнены.
Вам нужно инициализировать TOTALNUMS
, evens
, odds
и т.д. В конструкторе, поскольку все они зависят от значения, переданного в параметре array
конструктора.
Этот фрагмент кода
private final int TOTALNUMS = nums.length;
происходит до того, как nums был инициализирован, он все еще int nums [];
- у него нет размеров.
Вам нужно искать инициализаторы элементов и когда они выполняются по отношению к конструктору. Они запускаются перед конструктором. Только после этого (во время конструктора) вы инициализируете num, и это после того, как вы попытались использовать num.Length.
Переместите код, который зависит от nums.length, к конструктору, после того, как вы назначили nums, или в методе, который вызывается после того, как объект полностью создан (т.е. Не относится к нему в конструкторе вообще), добавьте другой метод на классе, который возвращает длину).
Попытка сделать слишком много в инициализаторах вызывает проблемы.
См. Первый ответ в этом вопросе:
Стационарный порядок инициализации Java
Или правила Java по порядку инициализации:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2
Все эти строки кода неправильны, поскольку эти строки выполняются по мере создания объекта до конструктора, который инициализирует 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()];
Я предлагаю преобразовать "evens" в "getEvens()" и вызывать getEvens() из основного, а не из инициализатора. То же самое для каждого из других полей, конвертировать в методы, которые вызываются позже.
nums
?