Scanner не выполняет nextLine() после next() или nextInt() (nextShort(), nextByte())

Действительно, такой код:
Scanner input = new Scanner(System.in);
int num = input.nextInt();String line = input.nextLine();
System.out.println("num: " + num + " line: " + line);
работает не так, как ожидается. Мы хотим, чтобы нам дали ввести число (например, 5), затем строку (например "apples"), а затем хотим увидеть в консоли:
num: 5 line: apples
Но нам дают ввести только число и на консоль сразу выводится
num: 5 line:
Причина такого поведения программы очень проста (хоть и не очевидна). Введя в консоль 5, мы нажали ввод. Вод передал в программу символ "\n". Именно этот символ и прочитала инструкция input.nextLine() вместо того, чтобы дать нам возможность ввести ещё одну строку. Те же проблемы мы увидим после вызова nextShort() или nextByte().
Чтобы избежать данной проблемы, достаточно использовать метод next() вместо nextLine() для чтения строки с консоли:
Scanner input = new Scanner(System.in);
int num = input.nextInt();String line = input.next();
System.out.println("num: " + num + " line: " + line);
Такой код отработает, как ожидается.
Кроме того, можно сделать "холостой" вызов nextLine() после вызовов метода nextInt():
Scanner input = new Scanner(System.in);
int num = input.nextInt();input.nextLine();String line = input.nextLine();
System.out.println("num: " + num + " line: " + line);
Такой код тоже отработает, как ожидается. Но "холостой" вызов придётся делать после каждого вызова nextInt().
Кроме того, сканнеру можно указать пропустить символ "\n" после методов nextInt() и ему подобных с помощью метода skip("\\R"). Но, также как в случае с nextLine() его придётся использовать после каждого вызова nextInt(). Хотя он может считаться более читаемым, так как прямо указывает пропустить символ перевода строки.
Также можно использовать разные сканеры для чтения чисел и чтения строк. Но каких-то преимуществ этот способ не даст.