Как обработать Nullpointer Exception и продолжить обработку файла?
У меня есть цикл обработки json файла на корректность всех полей. При прогоне всех group,если в одной из полей групп встретился null, то встречается Nullpointer Exception. Моя задача именно корректно обрабатывать эти null в полях, поэтому нужно чтобы, если какое-то поле в одном из объектов null, то все равно входить в цикл для обработки этого null Мой код
for (StudyGroup group : collection) {//детальная проверка файла на корректность
String line;
try {
Scanner scanner = new Scanner(System.in);
if (group.getStudentsCount().equals(null)) {
System.out.println("Незаполнено поле StudentCount у группы с id " + group.getId());
System.out.println("Хотите заполнить данный объект?В ином случае он не загрузиться(true/false)");
try {
if (scanner.hasNextLine()) {
line = scanner.nextLine().trim();
} else {
return null;
}
if (line.equals("true")) {
System.out.print("Введите значение для поля StudentsCount: ");
line = scanner.nextLine().trim();
if (line.equals("end")) {
System.out.println("Добавление элемента остановлено.");
return null;
}
if (group.setStudentsCount(Long.valueOf(line))) {
System.out.println("Поле StudentsCount дописано");
break;
}
}
if (line.equals("false")) {
collection.remove(group);
System.out.println("Тк вы не заполнили поле объект был пропущен");
break;
}
} catch (Exception e) {
System.out.println("Ошибка ввода поля StudentsCount, попробуйте еще раз или напишите end");
}
catch (NullPointerException e) {
System.out.println("Беда");
}
}
Мой Json
[{
"id":6984763508754014508,
"name":"P3111",
"coordinates":{
"x":32,
"y":360.0},
"creationDate": {
"date":{
"year":2021,
"month":5,
"day":5},
"time":{
"hour":11,
"minute":20,
"second":30,
"nano":682866300}},
"expelledStudents":5,
"formOfEducation":"DISTANCE_EDUCATION",
"semesterEnum":"FIRST",
"groupAdmin":{
"name":"Маша",
"passportID":"123",
"eyeColor":"BLACK",
"hairColor":"BLACK",
"nationality":"USA"}}]
Ответы (3 шт):
В данном случае писать логику программы на try-catch не лучший вариант. Проверяйте все значения на null перед их использованием.
Изменил на group.getStudentsCount()==null и все стало работать! Скорее всего ошибка была в том, что equals подходит для объектов, а null не является объектом. Сл-но если напишем == то все заработает.
Все равно это нормально работать не будет. Причина - удаление элемента из коллекции в процессе итерации. Так делать нельзя (по крайней мере тем способом, который у вас). Удаление элементов из коллекции - в процессе не очень хорошая практика в целом, но , если уж очень надо, то используйте итератор.
Кроме того, возвращать null - антипаттерн. Не делайте так никогда. В этом случае есть 3 решения: выбросить исключение, использовать паттрен null object , либо использовать optional.
Вам советовали использовать валидацию, не писать логику на базе try-catch, попробуйте хоть иногда прислушаться к тому, что говорят, раз уж сами просите помочь. Это не глупые советы. Ваш код с простейшей логикой превратился в спагетти благодаря глубокой вложенности. Запомните, что главное - читаемость кода, потому как машина исполнит любой, а вот вы будете вынуждены дебажить его неделями (как и произошло).
Раз вы хотите реализовать логику именно таким способом, то попробуйте хотя бы избавиться от дублирующей логики, написав отдельные методы. Например, так:
import java.util.Iterator;
import java.util.Optional;
import java.util.Scanner;
import java.util.function.Function;
import lombok.Data;
public class Parser {
private final Scanner scanner;
public Parser() {
this.scanner = new Scanner(System.in);
}
public void start(Iterable<StudyGroup> collection) {
Iterator<StudyGroup> iterator = collection.iterator();
while (iterator.hasNext()) {
StudyGroup group = iterator.next();
if (group.getStudentsCount() != null) continue;
System.out.println("Незаполнено поле StudentCount у группы с id " + group.getId());
System.out.println("Хотите заполнить данный объект? В ином случае он не загрузиться(true/false)");
if (parseAndEquals(Boolean::valueOf, true)) {
System.out.print("Введите значение для поля StudentsCount: ");
if (parseAndEquals(s -> s, "end")) {
System.out.println("Добавление элемента остановлено.");
break;
}
parse(Long::valueOf).ifPresent(line -> {
group.setStudentsCount(line);
System.out.println("Поле StudentsCount дописано");
});
} else {
iterator.remove();
System.out.println("Тк вы не заполнили поле объект был пропущен");
break;
}
}
}
private <T> boolean parseAndEquals(Function<String, T> converter, Object arg) {
return parse(converter).map(result->result.equals(arg)).orElseGet(()->false);
}
private <T> Optional<T> parse(Function<String, T> converter) {
try {
return Optional.of(converter.apply(scanner.nextLine().trim()));
} catch (Exception e) {
return Optional.empty();
}
}
}
Дебажить придется вам, потому как тестов не завезли, а разобраться в вашем коде уже достаточно сложно.