JavaのScannerクラスにおけるnextIntメソッドの動作仕様と入力バッファの不具合対策

こんにちは。ゆうせいです。

新人研修中に受講者から以下の質問をいただきました。

nextIntメソッドの直後にnextLineメソッドを呼び出すと、動作が変になります。

今回はこの質問に答えたいと思います。

Javaでキーボードからの入力を受け取る際、ScannerクラスのnextIntメソッドは非常によく利用されます。しかし、このメソッドを使用した直後にnextLineメソッドを呼び出すと、プログラムが意図せず入力をスキップしてしまう現象が発生します。この挙動は初心者が直面しやすい代表的な問題の一つです。

Scannerクラスと入力バッファの仕組み

コンピュータがキーボードからの入力を受け取る際、入力されたデータは一旦、入力バッファと呼ばれる一時的な保管場所に蓄えられます。Scannerクラスの各メソッドは、この保管場所からデータを取り出す役割を担います。

比喩を用いて説明すると、入力バッファは飲み物の自動販売機のコイン投入口から内部へ続く通路のようなものです。利用者が数字を入力してEnterキーを押すと、バッファには数字と改行文字(Enterの信号)が送り込まれます。

nextIntメソッドの動作

nextIntメソッドは、バッファの中から数値として解釈できる部分だけを読み取ります。ここで重要な点は、数値の直後にある改行文字をバッファに残したまま処理を終了するという特性です。

nextIntメソッドで発生する不具合の具体例

数値を入力した後に文字列を入力させようとするプログラムにおいて、以下の順序でメソッドを実行すると問題が発生します。

  1. nextIntメソッドで数値を読み取る。
  2. 次にnextLineメソッドで文字列を読み取ろうとする。

このとき、nextLineメソッドはバッファに残っていた改行文字を読み取った時点で、一行の入力が終了したと判断してしまいます。結果として、利用者が文字を入力する前にプログラムが次の処理へ進んでしまうのです。

ソースコードによる再現例

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("数値を入力してください:");
        int number = scanner.nextInt();
        
        System.out.println("名前を入力してください:");
        String name = scanner.nextLine(); // ここで入力がスキップされる
        
        System.out.println("入力された数値:" + number);
        System.out.println("入力された名前:" + name);
        
        scanner.close();
    }
}

nextIntメソッドを利用するメリットとデメリット

このメソッドの特性を理解するために、客観的な事実に基づいた利点と欠点を確認します。

メリット

  1. 型変換の簡略化入力された文字列を手動で数値型に変換する手間が省け、記述が簡潔になります。
  2. 連続入力への対応スペースで区切られた複数の数値を、ループ処理などで連続して取得する際に効率的です。

デメリット

  1. 改行文字の残留前述の通り、バッファに改行文字が残るため、後続のnextLineメソッドに悪影響を及ぼします。
  2. 入力不整合による例外数値以外の文字が入力された場合、InputMismatchExceptionというエラーが発生し、プログラムが強制終了します。

不具合を回避するための対策

この問題を解決するには、主に二つの方法があります。

1. 空読みによるバッファのクリア

nextIntメソッドを呼び出した直後に、一度だけnextLineメソッドを単独で実行します。これにより、バッファに残った改行文字を掃除して、次の入力を正常に受け取れる状態にします。

2. nextLineと型変換の併用

全ての入力を一旦nextLineメソッドで文字列として受け取り、その後にInteger.parseIntメソッドなどを用いて数値に変換する方法です。この手法であれば改行文字がバッファに残る心配がありません。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("数値を入力してください:");
        
        String str = scanner.nextLine();
        int number = Integer.parseInt(str);
        
        System.out.println("名前を入力してください:");
        String name = scanner.nextLine(); // ここで入力がスキップされる
        
        System.out.println("入力された数値:" + number);
        System.out.println("入力された名前:" + name);
        
        scanner.close();
    }

まとめ

JavaのScannerクラスにおけるnextIntメソッドの不具合は、入力バッファ内に改行文字が取り残されるという仕様に起因します。この挙動を正しく理解することは、Javaの入出力処理をマスターするための重要なステップです。

今後の学習ステップとして、まずは紹介した空読みの手法を自身のコードに取り入れ、動作がどのように変化するかを確認してください。次に、例外処理(try-catch文)を学習し、数値以外の値が入力された際の堅牢なプログラム作成に挑戦することをお勧めします。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。