-1

オブジェクトを作成してArrayListに追加しようとしています。コードは次のようになります。

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のコンストラクターは、ユーザーに文字列を要求し、スキャナーを介してそれを読み取ります。EssayQuestion()のコンストラクターは非常に似ています。

何か案は?

編集:ここに要求されたいくつかのコードがあります。はい、answerListは、初期化された後、何かが追加される前にnullとして表示されます。それが問題ですか?なぜそれが起こっているのですか?繰り返しになりますが、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;
}

}
4

3 に答える 3

1

createNewQuestion()問題は、コンストラクター内で呼び出していることである可能性があります。クラスのインスタンスを構築するときの処理の順序について何かが保証されているかどうかはわかりません。コンストラクターのコードは、の初期化の前に実行されている可能性がありますanswerList

の初期化(宣言ではない)をanswerListコンストラクターに移動してみてください。

もう1つの考えられる問題は、Testのコンストラクターがそのスーパークラスのコンストラクターを呼び出していないことです。コンストラクターの最初の行は。である必要がありますsuper();

null(ちなみに、と「空」の違いについては混乱しているようです。初期化がanswerList正常に完了すると、nullではありませんが、空のリストを指します。)

ファローアップ

スーパークラスのコンストラクターがどのように機能するかを思い出せませんでした。実際、明示的に呼び出さなくてもsuper()、スーパークラスコンストラクターは自動的に呼び出されます。「コンストラクターがスーパークラスコンストラクターを明示的に呼び出さない場合、Javaコンパイラーはスーパークラスの引数のないコンストラクターへの呼び出しを自動的に挿入します。」(http://docs.oracle.com/javase/tutorial/java/IandI/super.html)

そして、私は例外のスタックトレースからこれを認識すべきでした。スタックは、それTest()が呼び出していることを示しており、Survey()それが次に呼び出していTest.createNewQuestion()ます。2つのコンストラクターが非常に似ているというコメントから、これは驚くべきことではありません。

私はまだ問題の考えられる原因は物事が実行されている順序であると思います。が呼び出されるanswerList前に初期化させる方法はおそらくありません。Survey()

これは、私が最初に伝えたかったアドバイスに私をもたらします。それは、コンストラクターでこれらすべてのこと、特にユーザーの操作を行うべきではないということです。おそらく、のようなものと呼ばれる静的メソッドが各クラスにあるはずですcreateInstance()。これは、ユーザー入力を収集し、ローカル変数としてリストを作成し、それらのリストを引数として受け取るコンストラクターを呼び出します。

于 2012-10-27T04:53:55.277 に答える
1

あなたのコメントから@D_Jonesの答えまで、私はあなたがこのようなものを持っていると思います:

public class Survey{
    protected ArrayList<EssayQuestion> questionList;

    //your parent class methods;
}

その後、questionListにアクセスし、Testクラスから要素を追加しようとしています。ここでの問題は、questionListをインスタンス化していないことです。これは、questionListがまだnullであり、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
  }
}
于 2012-10-27T05:02:12.047 に答える
0

私はまだJavaに比較的慣れていないので、ここではかなりオフベースになる可能性がありますが、questionListを宣言しましたか?投稿されたコードには、questionListの宣言が表示されていません。私が言ったように、私はまだJavaに比較的慣れておらず、このサイトでの最初の日です。言うまでもなく、まだ学ぶ必要のあることがたくさんあります。

于 2012-10-27T04:46:04.240 に答える