2012-10-27 58 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