2012-10-27 54 views
-1

尝试创建一个对象并将其添加到ArrayList。代码类似于此:创建对象时Java线不可用?

class B{ 
    public ArrayList<Answer> answerList = new ArrayList<Answer>(); 

    questionList.add(new EssayQuestion()); 
    answerList.add(new StringAnswer()); 
} 

Exception in thread "main" java.lang.NullPointerException 
at main.Test.createNewQuestion(Test.java:31) 
at main.Survey.<init>(Survey.java:21) 
at main.Test.<init>(Test.java:9) 
at main.MainDriver.main(MainDriver.java:35) 

并在调试,对在飞机坠毁前我得到这个: Thread.dispatchUncaughtException(Throwable) line: not available

它的崩溃在 answerList.add(new StringAnswer()); ,我不知道为什么。

如果相关,questionList将在此代码块所在的超类中初始化。我正在访问它,因为它受到保护。 answerList是在本地创建的。

StringAnswer的构造函数向用户询问一个String并通过Scanner读取它。 EssayQuestion()的构造函数非常相似。

任何想法?

编辑:这是一些更多的代码按要求。是的,在初始化之后和添加任何内容之前,answerList显示为空。这是问题吗?为什么会发生? questionList再一次在父类中声明并初始化,因此可以不重新声明或初始化它吗?

public class Test extends Survey 
{ 
    public ArrayList<Answer> answerList; 

    public Test() 
    { 
      answerList = new ArrayList<Answer>(); 
    System.out.print("How many questions? "); 
    int numQuestions = kb.nextInt(); 
    for (int i = 0; i < numQuestions; i++) 
    { 
     displayMenu(); 
     createNewQuestion(); 
    } 
    } 

    public void createNewQuestion() 
    { 
    int input = -1; 
    do{ 
     System.out.print("Question Type: "); 
     input = kb.nextInt(); 
     System.out.println(); 

     switch (input) 
     { 
      case 1:  questionList.add(new EssayQuestion()); 
         answerList.add(new StringAnswer()); 
         break; 

这里是StringAnswer:

public class StringAnswer extends Answer 
{ 
String text; 

public StringAnswer() 
{ 
    setAnswer(); 

} 

public StringAnswer(String text) 
{ 
    this.text = text; 
} 

@Override 
public void display() 
{ 
    System.out.println(text);  
} 

public String getAnswer() 
{ 
    return text; 
} 

@Override 
public void setAnswer() 
{ 
    System.out.print("Enter Answer: "); 
    setAnswer(kb.nextLine()); 
    System.out.println(""); 
} 

public void setAnswer(String text) 
{ 
    this.text = text; 
} 

} 
+1

如果在'answerList.add(new StringAnswer());'崩溃,那么'answerList'显然是'null'。您是否尝试过使用调试器逐步执行代码? –

+0

如果你的代码不是太大,你可以发布它,而不是你发布的“类似代码”。 – Jayy

+0

是的,在任何东西被添加到它之前,anserList都是空的。我会根据要求发布更大的代码块。 – iaacp

回答

1

从您的意见@ D_Jones的答案,我想你已经是这样的:

public class Survey{ 
    protected ArrayList<EssayQuestion> questionList; 

    //your parent class methods; 
} 

之后,你正在访问questionList并试图从元素测试类添加到它。这里的问题是你没有实例化questionList。这意味着questionList仍然为空,并且当您尝试向questionList添加元素时,JVM会引发NullPointerException。

有是一对解决方案的它:

解决方案1 ​​:实例questionList在基类的构造函数。像这样的:

public class Survey{ 
    protected ArrayList<EssayQuestion> questionList; 

    public Survey(){ 
     questionList = new ArrayList<EssayQuestion>(); 
    } 
    //your parent class methods; 
} 

现在你可以在你的子类没有例外地访问它。

解决方案2:在您的子类的构造函数或任何您第一次尝试使用它的地方实例化它。

public class Survey{ 
    protected ArrayList<EssayQuestion> questionList; 

    //your parent class methods; 
} 


public class Test extends Survey 
{ 
    public ArrayList<Answer> answerList = new ArrayList<Answer>(); 

    public Test(){ 
    questionList = new ArrayList<EssayQuestion>(); //Option 1 
    } 

    public void createNewQuestion(){ 
    //If you've not initialized it in the constructor, try instantiating it in on first use 
    if(questionList == null){ //Option 2 
     questionList = new ArrayList<EssayQuestion>(); 
    } 

    //now you can access the questionList without an exception. 
    //this is because you've a valid instance of of ArrayList<EssayQuestion> to which the 
    //variable questionList points to 
    } 
} 
+0

谢谢你的回复,Sujay。 QuestionList被正确地声明和初始化,并且可以保留'Question's罚款。问题出在'answerList'上。我试图在构造函数中初始化它,并且在构造函数之前。它在调试器中的值仍然显示为空。 – iaacp

+0

@iaacp:第31行中有什么 - 您遇到NullPointerException的地方? – Sujay

0

我可以做的方式关闭基地在这里,因为我还是比较新到Java,但你申报questionList?发布的代码不显示questionList的声明。正如我所说我对Java还比较陌生,这是我在这个网站上的第一天。不用说我需要学习的东西还很多。

+1

据我所知,因为我在这个类的父类中声明了questionList,并且这个类扩展了这个,所以我可以自由使用它。我用保护包装它。 – iaacp

+0

@iaacp:所以你已经在父类中声明了'questionList'。但是,你在哪里实例化它?你得到NullPointerException的原因是你没有实例化这个变量。 – Sujay

+0

ahhh好的。所以它被宣布为受保护的。对不起,我在阅读这篇文章的第一遍时完全错过了。还在研究代码,看看我能不能找出一些东西。 –

1

问题可能是您在构造函数中调用createNewQuestion()。我不确定在构建类的实例时,如果有关于处理顺序的任何保证。在初始化answerList之前,构造函数中的代码可能正在执行。

尝试将answerList的初始化(但不是声明)移动到构造函数中。

另一个可能的问题是您的Test构造函数未调用其超类的构造函数。你的构造函数的第一行应该是​​。

(你似乎混淆,顺便说一下,关于null和“空”。如果answerList初始化成功完成,那么它不是空,但是它指向一个空列表。之间的差异)

跟进

我误解了超类构造函数是如何工作的。实际上,即使您没有明确地调用super(),也会自动调用超类的构造函数。 “如果构造函数没有显式调用超类的构造函数,那么Java编译器会自动插入对超类的无参构造函数的调用。” (http://docs.oracle.com/javase/tutorial/java/IandI/super.html)

而我应该从异常的堆栈跟踪中意识到这一点。堆栈显示Test()正在调用Survey(),然后调用Test.createNewQuestion()。从你对两个构造函数非常相似的评论来看,这并不奇怪。

我仍然认为问题的可能原因是执行顺序。在调用Survey()之前,可能无法使answerList初始化。

这让我首先想到的建议是,你不应该在构造函数中完成所有这些工作 - 特别是用户交互。我想说,你应该在每个类中都有一个类似于createInstance()的静态方法,它收集用户输入并将列表构建为局部变量,然后调用构造函数,将这些列表作为参数。

+0

我不想打电话给super();因为'Test'的构造函数与一些小的调整非常相似。所以我复制并粘贴,并添加了需要添加的内容。我试着在构造函数之外声明,然后在构造函数中初始化。同样的错误。 – iaacp