nextInt の後の nextLine が読み飛ばされる理由
改行文字の読み残しが原因です。判定と読み取りの単位を揃える設計を扱います。
なぜエラーが出ないのか
出力: 5:
(エラーなし)- javacは何も報告しません。文法として正しいためです
出力: 5:- 実際の挙動 — 期待した結果と食い違っている箇所
見つけ方- エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます
このエラーが出る典型パターン
パターン1
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 int n = sc.nextInt(); 7 ^ 8 String name = sc.nextLine(); 9 System.out.println(n + ":" + name); 10 } 11 }
出力: 5:期待: 5:Taiyo (コンパイルは通っています)
nextInt()は改行を読み残します。次のnextLine()がその改行を拾って空文字になる有名な罠です。
直し方: (空) を sc.nextLine(); にします。
広告
広告スロット(未設定)
パターン2
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 String s = sc.next (); ^ 7 System.out.println("[" + s + "]"); 8 } 9 }
入力: Taiyo Sato / 出力: [Taiyo]期待: [Taiyo Sato] (コンパイルは通っています)
next()は空白までの1単語だけを読みます。行全体を読むのはnextLine()です。
直し方: next を nextLine にします。
パターン3
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 while (sc.hasNext ()) { ^ 7 System.out.println(sc.nextLine()); 8 } 9 } 10 }
最終行が読み飛ばされることがある(コンパイルは通っています)
nextLineで読むならhasNextLineで判定します。判定と読み取りの単位を揃えるのが原則です。
直し方: hasNext を hasNextLine にします。
パターン4
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner("5 kg"); 6 int n = sc.nextInt(); 7 String unit = sc.nextLine(); ^ 8 System.out.println(n + unit); 9 } 10 }
出力: 5 kg期待: 5kg (コンパイルは通っています)
nextLineは残りの行をそのまま読むため先頭の空白も含みます。単語だけを取るならnextを使います。
直し方: nextLine を next にします。
パターン5
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner("1\n2\n3"); 6 int sum = 0; 7 while (sc.hasNextInt()) { 8 sum += sc.nextInt(); 9 sc.nextLine(); ^ 10 } 11 System.out.println(sum); 12 } 13 }
Exception in thread "main" java.util.NoSuchElementException: No line foundexited with code 1
hasNextIntで判定しnextIntで読んでいるのに余分なnextLineを挟むと、最後の行で読む相手がなくなり例外になります。
直し方: sc.nextLine(); を (空) にします。
よくある誤解
Scannerを2つ作れば直ると思いがちですが、悪化します。読み取り位置は入力ストリーム側にあり、共有されています。
実務での勘所
実務でこの種の事故を避ける定石は、nextIntとnextLineを混在させないことです。数値も含めてすべてnextLine()で1行ずつ文字列として読み取り、必要な箇所だけInteger.parseIntやDouble.parseDoubleで変換すれば、改行文字の読み残しという問題自体が発生しません。BufferedReaderを使う設計もこの発想の延長にあります。