Как исправить: Exception in thread "main" java.util.NoSuchElementException?

У меня сборник решения задач лабораторных с общим интерфейсом. Когда я запускаю прогу, то первый класс отрабатывает как надо, а на следующем сразу же ложится доходя до str.nextInt()

'''

package tasks;

import java.util.Arrays;
import java.util.List;

public class Main{
    public static void main(String[] args) {

        TaskInterface[] taskArray = {new Task1, new Task2(), new Task3(), new Task5(), new Task6(), new Task7(), new Task8(), new Task10(), new Task11()};
        List<TaskInterface> taskList = Arrays.asList(taskArray);

        for( TaskInterface t :  taskList) {
            t.execute();
        }

    }

}

'''

'''

package tasks;

import java.util.ArrayList;
import java.util.Scanner;

public class Task2 implements TaskInterface{

public void execute() {
    System.out.print("Введите число массива: ");
    Scanner str = new Scanner(System.in);
    int n = str.nextInt();
    ArrayList<Integer> numbers = new ArrayList<Integer>();
    for(int i = 0; i < n; i++){
        System.out.print("Введите числа массива: ");
        numbers.add(str.nextInt());
    }
    str.close();
    int i = (int) (Math.random() * n);
    int j = (int) (Math.random() * n);
    System.out.println("Счастливые числа: " + numbers.get(i) + "," + numbers.get(j) );
}

}

''' Сама ошибка:

введите сюда описание изображения

Подскажите пожалуйста почему так. Заранее благодарен за помощь)


Ответы (2 шт):

Автор решения: Котлетка еее

Возможно, остаётся перенос строки "\n" в буфере после ввода с клавиатуры в Task1. Попробуйте после каждого str.nextInt() прописывать сразу str.nextLine();
Это позволит очистить остатки ввода и впоследствии получать только введённое число.

→ Ссылка
Автор решения: Nowhere Man

Закрыв сканер, открытый для стандартного потока ввода System.in, вы также закрываете сам этот поток, после чего чтение данных с консоли становится невозможным.

Следовательно, НЕЛЬЗЯ закрывать сканер, открытый для общего стандартного потока ввода.

Если у вас однопоточное приложение, и задачи выполняются одна за одной, имеет смысл создать ОДИН экземпляр сканера и передавать его в ваши таски:

Scanner scanner = new Scanner(System.in);
List<TaskInterface> taskList = Arrays.asList(
   new Task1(scanner), new Task2(scanner),
   // ...
   new TaskN(scanner)
);
t.forEach(TaskInterface::execute);

Можно создать общий абстрактный класс для задач:

public abstract class AbstractTask implements TaskInterface {
    protected Scanner scanner;

    public AbstractTask(Scanner scanner) {
        this.scanner = scanner;
    }
}

Затем все конкретные задачи будут унаследованы от AbstractTask:

public class Task1 extends AbstractTask {
    public Task1(Scanner scanner) {
        super(scanner);
    }

    @Override
    public void execute() {
        int num = scanner.nextInt();
        System.out.println("Чётное? " + (num % 2 == 0 ? "Да" : "Нет"));
    }
}

и т.д.


Ссылки на аналогичные вопросы:

→ Ссылка