Я следую за большой книгой Big Java Late Objects, и у меня есть проблема с решением задач. Речь идет о наследовании. Существует класс Question и один дополнительный класс ChoiceQuestion, который расширяет его.
Но когда я запускаю код в своем тестовом классе, он вызывает нулевое исключение, и я не знаю, почему.
Exception in thread "main" java.lang.NullPointerException
at ChoiceQuestion.addChoice(ChoiceQuestion.java:12)
at TestClass.main(TestClass.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Вот мои классы:
public class Question {
private String text;
private String answer;
/**
* Constructs a queston with empty question and answer.
*/
public Question(){
text = "";
answer = "";
}
//=============Setter methods============
public void setText(String questionText){
text = questionText;
}
public void setAnswer(String correctResponse){
answer = correctResponse;
}
//==============Getter Methods=============
public boolean checkAnswer(String response){
return answer.equals(response);
}
public void display(){
System.out.println(text);
}
}
И вот мой подкласс:
class ChoiceQuestion extends Question {
private ArrayList<String> choices;
//=========Methods==============
public void addChoice(String choice,boolean correct){
choices.add(choice);
if(correct){
//convert choices.size() to string
String choiceString = "" + choices.size();
this.setAnswer(choiceString);
}
}
public void display(){
// Display the question text
super.display();
// Display the answer choices
for(int i=0;i<choices.size();i++){
int choiceNumber = i + 1;
System.out.println(choiceNumber + ": " + choices.get(i));
}
}
}
И мой тест Класс:
import java.util.Scanner;
public class TestClass {
public static void presentQuestion(Question q){
q.display();
System.out.println("Your answer: ");
Scanner in = new Scanner(System.in);
String response = in.nextLine();
System.out.println(q.checkAnswer(response));
}
public static void main(String[] args) {
Question first = new Question();
first.setText("James Gosling");
first.setAnswer("James Gosling");
ChoiceQuestion second = new ChoiceQuestion();
second.setText("In which country was the inventor of Java born? ");
second.addChoice("Austria", false);
second.addChoice("Canada",true);
second.addChoice("Denmark",false);
second.addChoice("United States",false);
presentQuestion(first);
presentQuestion(second);
}
}
choices
объектов никогда не инициализируется.
В Java объекты должны быть инициализированы, прежде чем вы сможете их использовать. Таким образом, попытка вызвать choices.add(choice)
дает такое исключение.
Часто бывает полезно инициализировать объекты-члены в конструкторах.
В этом случае похоже, что вы должны написать конструктор для ChoiceQuestion
и инициализировать свой choices
ArrayList
.
class ChoiceQuestion extends Question {
private ArrayList<String> choices;
ChoiceQuestion(){
choices = new ArrayList<>();
}
//...
Записывать личный выбор ArrayList = new ArrayList();
В классе, когда вы его объявили.
Перед использованием необходимо инициализировать список:
private List<String> choices = new ArrayList<String>();
Элемент choices
никогда не инициализируется, поэтому при первом попытке доступа к нему вы терпите неудачу с помощью NullPointerException
. Например, вы можете инициализировать его в определении класса:
class ChoiceQuestion extends Question {
private ArrayList<String> choices = new ArrayList<>();
// Rest of the class
choices