【问题标题】:Null Pointer Exception for arrays数组的空指针异常
【发布时间】:2014-04-30 02:47:41
【问题描述】:

我收到 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)

【问题讨论】:

  • 你认为你在哪里初始化nums
  • 但是nums需要从客户端格式化成数组,里面可能有多种元素
  • @Cdog101 哪一行是“IntegerArray.java:37”?
  • 私有最终 int TOTALNUMS = nums.length;
  • 这就是我的想法。在您的 num 未初始化之前,您不能这样做,“private final int TOTALNUMS = nums.length;”。将赋值放在构造函数中。

标签: java arrays nullpointerexception


【解决方案1】:

问题是你的代码有一个假设

private final int TOTALNUMS = nums.length;    

将在构造函数之后执行 ,因为从文本上讲它遵循它。这是一个不正确的假设——这一行在构造函数之前执行,此时nums 仍然是null。这就是导致异常的原因。

要解决这个问题,请将TOTALNUMS的初始化移到构造函数中:

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
}

最后,请注意,为nums 的长度保留一个单独的final 变量没有什么意义,因为它的长度始终可供您使用,如果您决定,您不需要“同步”这两者稍后将nums 设置为不同的数组。

【讨论】:

  • 我应该把它移到哪里?
【解决方案2】:

这段代码

private final int TOTALNUMS = nums.length; 

在初始化 nums 之前发生,它仍然是 int nums []; - 它没有大小。

【讨论】:

    【解决方案3】:

    我假设第 37 行是这一行:

       private final int TOTALNUMS = nums.length;
    

    问题是nums 那时还没有被初始化,因此它仍然有它的默认初始值。因此,执行num.length 会抛出 NPE。

    怎么样?

    你在构造函数中初始化nums。 Bur 构造函数主体中的代码仅在实例变量的初始化程序全部执行后才执行。

    你需要在构造函数中初始化TOTALNUMSevensodds等,因为它们都依赖于构造函数的array参数中传递的值。

    【讨论】:

      【解决方案4】:

      您需要查找成员初始值设定项以及它们何时相对于构造函数运行。它们在构造函数之前运行。只有在那之后(在构造函数期间)才初始化 num,也就是在您尝试使用 num.Length 之后。

      将依赖于 nums.length 的代码移到构造函数中,在您分配 nums 之后,或者在对象完全创建后调用的方法中(即,根本不要在构造函数中调用它,在返回长度的类上添加另一个方法)。

      试图在初始化器中做太多事情会导致麻烦。

      查看此问题的第一个答案:

      Java Static Initialization Order

      或者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()" 并从 main 而不是从初始化程序调用 getEvens()。 其他每个字段都相同,转换为稍后调用的方法。

      【讨论】:

      • 如果你看大部分代码都依赖于 nums.length。有没有办法解决这个问题?
      • 是的,确保在对象完全构造之后调用任何依赖于 nums.length 的代码,或者至少在构造函数中分配“nums = array”的行之后调用。
      • 考虑将 TOTALNUMS 从一个字段更改为 getTotalNums() 方法,其他字段相同,并将调用移至 main()。
      猜你喜欢
      • 1970-01-01
      • 2017-01-30
      • 1970-01-01
      • 1970-01-01
      • 2013-03-22
      • 1970-01-01
      • 2013-01-18
      • 1970-01-01
      相关资源
      最近更新 更多