Java で文字列が数値かどうかをチェックする方法

JavaBeginner
オンラインで実践に進む

はじめに

この実験では、Java で与えられた文字列が数値を表すかどうかをチェックするさまざまな方法を学びます。まず、文字列を整数にパースしようとする方法と、文字列が有効な数値でない場合の潜在的なエラーの処理方法を探ります。

その後、より柔軟で堅牢な数値チェックを行うために正規表現 (regular expressions) の力を活用する方法を学びます。最後に、負の数や小数値を表す文字列も扱えるように理解を拡張し、数値チェックが包括的なものになるようにします。

文字列を整数にパースする試み

このステップでは、Java で文字列を整数(整数値)に変換する方法を探ります。これは、ユーザーから数値入力を取得したり、ファイルから数値を読み取ったりする際に特に必要となる、プログラミングにおける一般的なタスクです。

Java では、Integer.parseInt() メソッドを使用してこれを行う組み込みの方法が用意されています。しかし、文字列が実際に有効な数値を表さない場合はどうなるでしょうか?簡単な Java プログラムを書いて確かめてみましょう。

  1. WebIDE エディタで HelloJava.java ファイルが開いていない場合は、開きます。

  2. ファイルの内容全体を次のコードに置き換えます。

    public class HelloJava {
        public static void main(String[] args) {
            String numberString = "123";
            int number = Integer.parseInt(numberString);
            System.out.println("Successfully parsed: " + number);
    
            String invalidString = "abc";
            try {
                int invalidNumber = Integer.parseInt(invalidString);
                System.out.println("This line will not be reached.");
            } catch (NumberFormatException e) {
                System.out.println("Error: Could not parse '" + invalidString + "' to an integer.");
                System.out.println("Exception details: " + e.getMessage());
            }
        }
    }
    

    このコードの新しい部分を見てみましょう。

    • String numberString = "123";: 文字列変数 numberString を作成し、値 "123" を割り当てます。
    • int number = Integer.parseInt(numberString);: これが変換の核心部分です。Integer.parseInt() は、文字列 "123" を整数に変換しようとします。"123" は有効な整数表現なので、これは成功し、整数値 123number 変数に格納されます。
    • String invalidString = "abc";: 別の文字列変数 invalidString を作成し、値 "abc" を割り当てます。この文字列は有効な整数を表していません。
    • try { ... } catch (NumberFormatException e) { ... }: これは try-catch ブロックで、Java でエラー(例外)を処理するために使用されます。
      • try ブロック内のコードは、エラーを引き起こす可能性のある操作を記述する場所です。この場合、Integer.parseInt(invalidString) です。
      • Integer.parseInt("abc")"abc" が有効な数値でないために失敗すると、NumberFormatException が「スロー」されます。
      • catch (NumberFormatException e) ブロックは、この特定のタイプの例外を「キャッチ」します。その後、catch ブロック内のコードが実行されます。
    • System.out.println("Error: Could not parse '" + invalidString + "' to an integer.");: この行は、NumberFormatException が発生した場合に出力されます。
    • System.out.println("Exception details: " + e.getMessage());: これは、例外オブジェクト e が提供するエラーに関するより具体的なメッセージを出力します。
  3. ファイルを保存します(Ctrl+S または Cmd+S)。

  4. ターミナルでプログラムをコンパイルします。

    javac HelloJava.java
    

    エラーがなければ、何も出力されません。

  5. コンパイルされたプログラムを実行します。

    java HelloJava
    

    次のような出力が表示されるはずです。

    Successfully parsed: 123
    Error: Could not parse 'abc' to an integer.
    Exception details: For input string: "abc"
    

    この出力は、最初のパース試行は成功したが、無効な文字列 "abc" を使った 2 回目の試行では NumberFormatException が発生し、catch ブロックがエラーメッセージを出力することでエラーを適切に処理したことを示しています。

これは、すべての文字列が成功裏にパースできるわけではないため、文字列を数値に変換する際に潜在的なエラーを処理する重要性を示しています。try-catch ブロックを使用することは、Java でこのような状況を管理する標準的な方法です。

正規表現を使用した数値チェック

前のステップでは、文字列が有効な整数でない場合、Integer.parseInt() が例外をスローすることを見ました。try-catch はエラーが発生したときにそれを処理するのに便利ですが、場合によっては、変換を試みる 前に 文字列が数値にパース できるか どうかをチェックしたいことがあります。このような場合に正規表現 (Regular Expressions, Regex) が便利です。

正規表現は、文字列内の文字の組み合わせをマッチさせるために使用される強力なパターンです。簡単な正規表現パターンを使用して、文字列が数字のみで構成されているかどうかをチェックすることができます。

  1. WebIDE エディタで HelloJava.java ファイルを開きます。

  2. ファイルの内容全体を次のコードに置き換えます。

    public class HelloJava {
        public static void main(String[] args) {
            String numberString = "123";
            String invalidString = "abc";
            String mixedString = "123a";
    
            System.out.println("Checking string: \"" + numberString + "\"");
            if (numberString.matches("\\d+")) {
                System.out.println("  Matches the pattern (contains only digits).");
                int number = Integer.parseInt(numberString);
                System.out.println("  Parsed integer: " + number);
            } else {
                System.out.println("  Does not match the pattern.");
            }
    
            System.out.println("\nChecking string: \"" + invalidString + "\"");
            if (invalidString.matches("\\d+")) {
                System.out.println("  Matches the pattern (contains only digits).");
            } else {
                System.out.println("  Does not match the pattern.");
            }
    
            System.out.println("\nChecking string: \"" + mixedString + "\"");
            if (mixedString.matches("\\d+")) {
                System.out.println("  Matches the pattern (contains only digits).");
            } else {
                System.out.println("  Does not match the pattern.");
            }
        }
    }
    

    新しい部分を分解してみましょう。

    • numberString.matches("\\d+"): これが重要な部分です。matches() メソッドは、Java のすべての文字列オブジェクトで使用できます。このメソッドは、文字列全体が指定された正規表現パターンに一致するかどうかをチェックします。
    • "\\d+": これが正規表現パターンです。
      • \\d: これは任意の数字 (0 から 9) とマッチします。\ は Java 文字列では特殊文字なので、エスケープするために \\ を使用します。
      • +: これは数量指定子で、直前の要素が「1 つ以上」であることを意味します。したがって、\\d+ は「1 つ以上の数字」を意味します。
    • if 文は matches() の結果をチェックします。true が返された場合、文字列は 1 つ以上の数字のみで構成されていることを意味します。false が返された場合、文字列には数字以外の文字が含まれているか、空であることを意味します。
  3. ファイルを保存します(Ctrl+S または Cmd+S)。

  4. ターミナルでプログラムをコンパイルします。

    javac HelloJava.java
    

    コンパイルが成功すると、何も出力されないはずです。

  5. コンパイルされたプログラムを実行します。

    java HelloJava
    

    次のような出力が表示されるはずです。

    Checking string: "123"
      Matches the pattern (contains only digits).
      Parsed integer: 123
    
    Checking string: "abc"
      Does not match the pattern.
    
    Checking string: "123a"
      Does not match the pattern.
    

    ご覧の通り、matches("\\d+") チェックによって、"123" が数字のみで構成されていることが正しく識別され、"abc""123a" はパターンに一致しないことがわかります。このアプローチにより、パースを試みる前に文字列の形式を検証でき、場合によっては NumberFormatException を回避できます。

負の数と小数を扱う

前のステップでは、正の整数のパースに焦点を当てました。しかし、数値には負の数や小数点を持つ数もあります。このステップでは、Java で文字列を数値に変換する際にこれらのケースをどのように扱うかを学びます。

Java では、異なるタイプの数値をパースするための異なるメソッドが用意されています。

  • Integer.parseInt(): 整数(整数値)用。
  • Double.parseDouble(): 小数点を持つ数(浮動小数点数)用。

プログラムを修正して、負の整数と小数を扱えるようにしましょう。

  1. WebIDE エディタで HelloJava.java ファイルを開きます。

  2. ファイルの内容全体を次のコードに置き換えます。

    public class HelloJava {
        public static void main(String[] args) {
            String positiveIntString = "456";
            String negativeIntString = "-789";
            String decimalString = "123.45";
            String invalidString = "not a number";
    
            // Handling Integers (positive and negative)
            System.out.println("Attempting to parse integers:");
            try {
                int positiveInt = Integer.parseInt(positiveIntString);
                System.out.println("  Parsed '" + positiveIntString + "' as integer: " + positiveInt);
            } catch (NumberFormatException e) {
                System.out.println("  Could not parse '" + positiveIntString + "' as integer.");
            }
    
            try {
                int negativeInt = Integer.parseInt(negativeIntString);
                System.out.println("  Parsed '" + negativeIntString + "' as integer: " + negativeInt);
            } catch (NumberFormatException e) {
                System.out.println("  Could not parse '" + negativeIntString + "' as integer.");
            }
    
            try {
                int decimalAsInt = Integer.parseInt(decimalString);
                System.out.println("  Parsed '" + decimalString + "' as integer: " + decimalAsInt);
            } catch (NumberFormatException e) {
                System.out.println("  Could not parse '" + decimalString + "' as integer.");
            }
    
            // Handling Decimal Numbers
            System.out.println("\nAttempting to parse decimal numbers:");
            try {
                double decimal = Double.parseDouble(decimalString);
                System.out.println("  Parsed '" + decimalString + "' as double: " + decimal);
            } catch (NumberFormatException e) {
                System.out.println("  Could not parse '" + decimalString + "' as double.");
            }
    
            try {
                double intAsDouble = Double.parseDouble(positiveIntString);
                System.out.println("  Parsed '" + positiveIntString + "' as double: " + intAsDouble);
            } catch (NumberFormatException e) {
                System.out.println("  Could not parse '" + positiveIntString + "' as double.");
            }
    
             try {
                double invalidAsDouble = Double.parseDouble(invalidString);
                System.out.println("  Parsed '" + invalidString + "' as double: " + invalidAsDouble);
            } catch (NumberFormatException e) {
                System.out.println("  Could not parse '" + invalidString + "' as double.");
            }
        }
    }
    

    ここで行われていることは次の通りです。

    • 正の整数、負の整数、小数、および無効な文字列を表す文字列が用意されています。
    • try-catch ブロック内で Integer.parseInt() を使用して、文字列を整数としてパースしようとします。Integer.parseInt() は負符号 (-) を扱うことができます。ただし、文字列に小数点や数字以外の文字が含まれている場合、NumberFormatException をスローします。
    • try-catch ブロック内で Double.parseDouble() を使用して、文字列を小数(double 型)としてパースしようとします。Double.parseDouble() は整数と小数点を持つ数の両方を扱うことができます。double 型の有効な表現ではない文字列に対しては、NumberFormatException をスローします。
  3. ファイルを保存します(Ctrl+S または Cmd+S)。

  4. ターミナルでプログラムをコンパイルします。

    javac HelloJava.java
    

    コンパイルが成功すると、何も出力されないはずです。

  5. コンパイルされたプログラムを実行します。

    java HelloJava
    

    次のような出力が表示されるはずです。

    Attempting to parse integers:
      Parsed '456' as integer: 456
      Parsed '-789' as integer: -789
      Could not parse '123.45' as integer.
    
    Attempting to parse decimal numbers:
      Parsed '123.45' as double: 123.45
      Parsed '456' as double: 456.0
      Could not parse 'not a number' as double.
    

    この出力は、Integer.parseInt() が正の整数と負の整数を正しくパースしたが、小数の文字列では失敗したことを示しています。Double.parseDouble() は小数の文字列と整数の文字列の両方を成功裏にパースし(整数を double 型として表現、例えば 456.0)、無効な文字列では失敗しました。

このステップでは、異なる数値タイプに適したパースメソッドを使用する方法を示し、入力文字列が期待される形式でない場合に潜在的な NumberFormatException エラーを処理するために try-catch ブロックを使用する重要性を強調しています。

まとめ

この実験では、Java で文字列が数値かどうかをチェックする方法を学びました。まず、Integer.parseInt() を使って文字列を整数にパースする方法を調べ、文字列が有効な整数表現でない場合、このメソッドが NumberFormatException をスローすることを理解しました。また、try-catch ブロックを使ってこの例外を処理し、非数値の文字列を適切に管理する方法を見ました。

これを基に、次に正規表現を使って数値文字列のチェックを行う、より柔軟なアプローチを学びました。正規表現は様々な形式を扱うことができます。最後に、文字列が数値を表すかどうかを判断する際に、負の数や小数を扱う方法についても理解を深めました。