我搜索了很多,而且我对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;
}
}
答案 0 :(得分:3)
当您拥有包含行号的堆栈时,调试NullPointerException
应该相当简单。使用IDE,您应该能够突破该行并查看确切的问题。还有良好的ole print语句调试。如果你能够单步执行条件运算符,我打赌你会发现问题所在。在执行布尔逻辑时,您几乎总是希望使用&&
,因为它会短路并避免您找到的问题。 &
真的是按位and
;它将执行操作符的两个侧面,导致看起来像你的问题。
答案 1 :(得分:1)
将for循环更改为for ( int i = 0 ; i < zodiacDates.size(); i++ )
如果您使用<=
,zodiacDates.get(i)
将在到达结尾时返回null。
还可以使用以下语句填充您的arraylist:
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类中有一些静态变量,而您的函数getIndexBySign
和getIndexByDate
仅使用静态内容,不使用Object依赖变量。理想情况下,您可以将它们设置为静态,然后使用Dates.getIndexBySign(...)
和Dates.getIndexByDate(...)
调用它们,并且可以删除日期对象声明。
这就是我的全部!