空指针异常解决

时间:2016-02-14 22:38:10

标签: java

我搜索了很多,而且我对java很新,所以我试图创建一个基本程序来执行以下操作

用户将插入出生日期或占星标志

该程序将告诉用户他们的标志是什么或特定占星经历的日期范围。

我目前正处于这条线...... "     ourDate.getIndexByDate(myDay); " 给出空指针异常。 同时,ourDate调用的方法也是如此。

java.lang.NullPointerException
    at Dates.getIndexByDate(Dates.java:68)
    at Dates.main(Dates.java:49)

我有以下代码:

import java.util.ArrayList;
import java.util.Scanner;

public class Dates {

    private static ArrayList<Double> zodiacDates;
    private static ArrayList<String> zodiac;

    public static void main(String[] args) {
        ArrayList<Double> zodiacDates = new ArrayList<Double>()
        {{ 
            add(1.19);
            add(2.18);
            add(3.20);
            add(4.21);
            add(5.20);
            add(6.20);
            add(7.22);
            add(8.22);
            add(9.22);
            add(10.22);
            add(11.21);
            add(12.21);
        }};
        ArrayList<String> zodiac = new ArrayList<String>()
        {{
            add("Capricorn");
            add("Aquarius");
            add("Pisces");
            add("Aries");
            add("Taurus");
            add("Gemini");
            add("Cancer");
            add("Leo");
            add("Virgo");
            add("Libra");
            add("Scorpio");
            add("Sagittarius");     
        }};
        Scanner keyboard = new Scanner(System.in);
        System.out.println("Enter your birthdate in the form of a double");
        Double myDay = keyboard.nextDouble();
        System.out.println("Enter your horoscope sign if you know it");
        String ourSign = keyboard.nextLine();
        Dates ourDate = new Dates();
        System.out.println("Enter your birthdate in the form of a double");
        ourDate.getIndexByDate(myDay);
        ourDate.getIndexBySign(ourSign);    
    }

    public int getIndexBySign(String pName)
    {
        for (int w = 0; w < zodiac.size(); w++)
        {
            String sign = zodiac.get(w);
            if (pName.equals(sign))
            {
                return w;
            }
        } 

        return -1;
    }

    public int getIndexByDate(Double myDay)
    {
        for (int i = 0; i <= zodiacDates.size(); i++)
        {
            Double variable = zodiacDates.get(i);
            if ((myDay <= variable && myDay > zodiacDates.get(i-1)) || (myDay < 1.19 || myDay >= 12.22 ) )
            {
                return i;
            }   
        }
        return -1;
    }
}

3 个答案:

答案 0 :(得分:3)

当您拥有包含行号的堆栈时,调试NullPointerException应该相当简单。使用IDE,您应该能够突破该行并查看确切的问题。还有良好的ole print语句调试。如果你能够单步执行条件运算符,我打赌你会发现问题所在。在执行布尔逻辑时,您几乎总是希望使用&&,因为它会短路并避免您找到的问题。 &真的是按位and;它将执行操作符的两个侧面,导致看起来像你的问题。

答案 1 :(得分:1)

  1. 使用&amp;&amp; for&amp;和||为|在你的if条件下。 (&amp;和|是逐位运算符)
  2. 将for循环更改为for ( int i = 0 ; i < zodiacDates.size(); i++ ) 如果您使用<=zodiacDates.get(i)将在到达结尾时返回null。

  3. 还可以使用以下语句填充您的arraylist:

  4. ArrayList<Double> zodiacDates = new ArrayList<Double>(); zodiacDates.add( 9.22 ); zodiacDates.add( 10.22 );

    .....

    和zodiac as

    ArrayList<String> zodiac = new ArrayList<String>();
    zodiac.add("Capricorn");
    zodiac.add("Leo");
    

答案 2 :(得分:0)

错误来自静态变量以及如何在函数中覆盖它们。您有静态(〜=全局)列表private static ArrayList<Double> zodiacDates;private static ArrayList<String> zodiac;

问题是你在main函数中再次声明它们,但不是静态的,你初始化的变量只是你的main函数的本地变量。然后当你在2个函数中调用“全局”静态变量时,它们是未初始化的,这意味着你得到一个漂亮而漂亮的NullPointerException,因为变量中没有任何内容。只需在main中删除初始化的声明部分:

public static void main(String[] args) {
    zodiacDates = new ArrayList<Double>()
    {{ 
        add(1.19);
        add(2.18);
        add(3.20);
        add(4.21);
        add(5.20);
        add(6.20);
        add(7.22);
        add(8.22);
        add(9.22);
        add(10.22);
        add(11.21);
        add(12.21);
    }};
    zodiac = new ArrayList<String>()
    {{
        add("Capricorn");
        add("Aquarius");
        add("Pisces");
        add("Aries");
        add("Taurus");
        add("Gemini");
        add("Cancer");
        add("Leo");
        add("Virgo");
        add("Libra");
        add("Scorpio");
        add("Sagittarius");     
    }};
    Scanner keyboard = new Scanner(System.in);
    System.out.println("Enter your birthdate in the form of a double");
    Double myDay = keyboard.nextDouble();
    System.out.println("Enter your horoscope sign if you know it");
    String ourSign = keyboard.nextLine();
    System.out.println("Enter your birthdate in the form of a double");
    Dates.getIndexByDate(myDay);
    Dates.getIndexBySign(ourSign);    
}

您还会得到一个ArrayIndexOutOfBoundsException,因为在某些情况下您尝试访问ArrayList的未存在元素:

for (int i = 0; i <= zodiacDates.size(); i++)
{
    Double variable = zodiacDates.get(i);
    if ((myDay <= variable && myDay > zodiacDates.get(i-1)) || (myDay < 1.19 || myDay >= 12.22 ) )
    {
        return i;
    }   
}

即使i = 0(在第一次循环执行时),也使用zodiacDates.get(i-1)。这意味着您将尝试访问第-1个元素,当然不存在。
为了避免它在你的for循环中以i = 1开始。修复此问题还会显示您使用i <= zodiacDates.size()
问题是当您到达for循环中的最后一个元素时(当i = zodiacDates.size()时),您将比最后一个元素更远元件。实际上,索引以 0 开头,因此最后一个元素的索引为zodiacDates.size() - 1
解决方案是使用<代替<=你使用了 zodiac 列表。

正如您在if语句中尝试解决的那样,剩下的问题是日期是在12月到1月之间。你的if语句包含这个检查(myDay < 1.19 || myDay >= 12.22 ),这意味着如果你在这个时间间隔内有一个输入日期,它将在第一次到达它时使satetement为真,这意味着它将返回1(i的值)
因此你必须在你的循环之前检查这个间隔......或者你不要! 你实际上知道如果在循环中没有检测到日期,它只能是Sagitarius。现在,如果您不需要无效的输入检测(您实际上并不是因为有人可以输入类似5.98的日期并且仍然被投入星座),您可以使用射手座作为默认值,并在循环后返回0 。 给予:

public static int getIndexByDate(Double myDay)
{
    if (myDay < 1.19 || myDay >= 12.22 ) return 0; //Not necessary
    for (int i = 1; i < zodiacDates.size(); i++)
    {
        Double variable = zodiacDates.get(i);
        if (myDay <= variable && myDay > zodiacDates.get(i-1) )
        {
            return i;
        }   
    }

    return -1; //Or return 0; as default case.
}

Last Class详细信息,您的Dates类中有一些静态变量,而您的函数getIndexBySigngetIndexByDate仅使用静态内容,不使用Object依赖变量。理想情况下,您可以将它们设置为静态,然后使用Dates.getIndexBySign(...)Dates.getIndexByDate(...)调用它们,并且可以删除日期对象声明。

这就是我的全部!