入門 ローカル(VS Code + Java) 約15分

文字列と数値を変換する

入力された値が文字列で届くことを Scanner で確かめ、Integer.parseInt と String.valueOf で型を変換するレッスン。

キーボードから入力された値も、Web の画面のフォームに入力された値も、プログラムにはまず文字列として届きます。120 と入力しても、届くのは数値の 120 ではなく "120" という文字列です。この回は、その文字列を数値に変換する形を扱います。

引き続き VS Code とローカルの Java 環境を使います。この回のコードはキーボードからの入力を待つので、実行ボタンを押しても入力できない場合は、ターミナルで javac Main.javajava Main の手順で実行してください。ターミナルで日本語が化けるときは、前の回の注記と同じく chcp 65001 を先に実行します。

入力を受け取る

Scanner は、キーボードからの入力を受け取る道具です。Main.java を次の内容にします。

import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    System.out.print("個数を入力してください: ");
    String input = scanner.nextLine();

    System.out.println("入力された値: " + input);
  }
}

1行目の import と、new Scanner(...) の形は ArrayList の回と同じです。new Scanner(System.in)System.in はキーボードからの入力を指します。これまで使ってきた System.out(画面への出力)と対になる書き方です。

System.out.printprintln と違って改行しないので、入力欄が同じ行に続きます。

実行すると入力待ちで止まります。3 と入力して Enter を押してください。

個数を入力してください: 3
入力された値: 3

画面には 3 と出ていますが、input の型は String です。数値ではありません。

そのままでは計算できない

1個120円として合計を出したくなります。String input = ... の下に、この行を足してみてください。

int total = input * 120;

これはコンパイルが通りません。Stringint* で掛けることはできず、javac は「型が合わない」という趣旨のエラーを出して止まります。表示される文面は環境の言語設定によって変わりますが、指されている行は同じです。

前回の NullPointerException は実行してみるまで分かりませんでしたが、こちらは実行の前に止まります。型が合わない間違いは、コンパイラが見つけてくれます。

Integer.parseInt で数値にする

変換を1行はさみ、表示する内容も合計に変えます。

import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);

    System.out.print("個数を入力してください: ");
    String input = scanner.nextLine();

    int count = Integer.parseInt(input);
    int total = count * 120;

    System.out.println("合計: " + total + "円");
  }
}
個数を入力してください: 3
合計: 360円

Integer.parseInt(input) は、文字列を int に変換して返します。parse は「解釈する」という意味です。count の型が int になったので、* 120 の計算が通ります。

Scanner には nextInt() という「整数として読む」メソッドもあります。ただし数値でない文字が入力されたときに失敗する点は同じです。この回では、届いた文字列をいったん受け取ってから変換する形で進めます。

数値にできない文字を入れると落ちる

もう一度実行して、今度は abc と入力してください。

個数を入力してください: abc
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
	at java.base/java.lang.Integer.parseInt(Integer.java:565)
	at java.base/java.lang.Integer.parseInt(Integer.java:662)
	at Main.main(Main.java:10)

NumberFormatException は「数値の形式ではない」という意味です。For input string: "abc" に、変換しようとした値がそのまま出ています。

前回と違うのは、at で始まる行が4つあることです。この一覧をスタックトレースと呼びます。

上の3つは java.base で始まっていて、Java 側のファイルです。自分で直せる場所ではありません。探すのは、自分が書いたファイル名が出ている行です。ここでは一番下の at Main.main(Main.java:10) で、10行目の Integer.parseInt が該当します。

このコードは Temurin 25 で確認しています。java.base で始まる行の番号(Integer.java:565 など)は Java のバージョンによって変わります。見るのは Main.java の行番号のほうです。

失敗しやすい入力

数字に見えても変換できない値があります。

入力Integer.parseInt の結果
"120"120
" 3 "(前後に空白)失敗する
"1.5"失敗する
"abc"失敗する
""(何も入力せずに Enter)失敗する

空白は trim() で落とせます。コピーして貼り付けた値には空白が混ざりやすいので、入力を受け取る場面ではよく使います。先ほどのコードの10行目を、次のように書き換えます。

int count = Integer.parseInt(input.trim());

ただし何も入力せずに Enter を押した場合は、trim() を通しても失敗します。 空白だけを入力した場合も、trim() の結果が空になるので同じです。値が入っているかどうかは、変換とは別に確かめる必要があります。

小数を受け取りたい場合は Double.parseDouble を使います。Integer.parseInt("1.5") は失敗しますが、Double.parseDouble("1.5")1.5 になります。整数として読むメソッドに小数を渡しても、切り捨てにはならず失敗します。

逆に、数値を文字列にする

計算結果を文字列として扱いたいときは String.valueOf を使います。

public class Main {
  public static void main(String[] args) {
    int total = 360;
    String text = String.valueOf(total);

    System.out.println(text.length());
  }
}
3

text"360" という3文字の文字列なので、length()3 を返します。total のままでは length() を呼べません。

なお System.out.println("合計: " + total) のように + でつなぐ場合は、変換を書かなくても文字列として扱われます。変換を明示するのは、結果を String の変数に入れたいときや、文字数を数えるような文字列としての操作をしたいときです。

変換の早見表

やりたいこと書き方
文字列 → 整数Integer.parseInt(s)
文字列 → 小数Double.parseDouble(s)
数値 → 文字列String.valueOf(n)
数値を文字列に混ぜて表示する"合計: " + n

この先どこで出てくるか

画面のフォームに入力された値は、文字列です。 Part 4 で JavaScript から入力欄を読むときも、取り出せるのは文字列で、この回と同じ話になります。

そこから先は少し違います。Web アプリがサーバーへデータを送るときは JSON という形式を使いますが、JSON は数値も書ける形式です。{"count": 3}3 は文字列ではなく数値として書かれています。Spring Boot では、届いた JSON を宣言した Java の型へ変換する仕組みが用意されているので、Integer.parseInt を自分で書く場面はほとんどありません。

それでも、変換が失敗しうるという性質は残ります。 数量の欄に文字が入力されれば、変換はどこかで失敗します。違うのは出てくる場所です。この回のように画面へスタックトレースが出るのではなく、ブラウザにはエラーの応答が返り、詳しい内容はサーバー側のログに出ます。探す場所が変わるだけで、読むものは同じだと思っておいてください。

次の回へ

次はクラスとオブジェクトです。ここまでは値を1つずつ変数に入れてきましたが、関連するデータをひとまとめにして名前を付ける方法に入ります。Spring Boot でデータを扱うときの土台になります。