How to check if a String is numeric in Java

Learn how to check if a string is numeric in java with practical examples, diagrams, and best practices. Covers java, string, numeric development techniques with visual explanations.

How to Check if a String is Numeric in Java

Hero image for How to check if a String is numeric in Java

Learn various robust methods to determine if a given Java String contains only numeric characters, handling different edge cases and performance considerations.

Determining whether a Java String represents a numeric value is a common task in programming. This seemingly simple requirement can become complex when considering various definitions of "numeric" – integers, decimals, positive/negative numbers, and even scientific notation. This article explores several reliable methods, from basic character checks to leveraging built-in library functions, helping you choose the best approach for your specific needs.

Understanding the 'Numeric' Definition

Before diving into implementation, it's crucial to define what constitutes a 'numeric' string for your application. Do you need to check for:

  • Integers only? (e.g., "123", "-45")
  • Decimal numbers? (e.g., "3.14", "-0.5")
  • Positive numbers only?
  • Numbers with leading/trailing spaces? (e.g., " 123 ")
  • Scientific notation? (e.g., "1.23e-5")

Each definition might lead to a different implementation strategy. Most common scenarios involve checking for valid integers or floating-point numbers.

flowchart TD
    A[Start] --> B{Input String?}
    B -- No --> E[Invalid]
    B -- Yes --> C{Definition of 'Numeric'?}
    C -- Integer --> D1[Try Integer.parseInt()]
    C -- Decimal --> D2[Try Double.parseDouble()]
    C -- Custom --> D3[Regex or Character.isDigit()]
    D1 --> F{Exception?}
    D2 --> F{Exception?}
    D3 --> F{Match?}
    F -- Yes --> E[Invalid]
    F -- No --> G[Valid Numeric]
    G --> H[End]
    E --> H[End]

Decision flow for checking if a String is numeric

Method 1: Using Integer.parseInt() or Double.parseDouble()

The most straightforward way to check if a string represents a number is to attempt to parse it into the desired numeric type. If the string is not a valid number, these methods will throw a NumberFormatException. This approach is robust for standard integer and floating-point formats.

public class NumericCheck {

    public static boolean isInteger(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static boolean isDouble(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public static void main(String[] args) {
        System.out.println("Is '123' an integer? " + isInteger("123")); // true
        System.out.println("Is '-45' an integer? " + isInteger("-45")); // true
        System.out.println("Is '123.45' an integer? " + isInteger("123.45")); // false
        System.out.println("Is 'abc' an integer? " + isInteger("abc")); // false
        System.out.println("Is '' an integer? " + isInteger("")); // false
        System.out.println("Is null an integer? " + isInteger(null)); // false

        System.out.println("\nIs '3.14' a double? " + isDouble("3.14")); // true
        System.out.println("Is '-0.5' a double? " + isDouble("-0.5")); // true
        System.out.println("Is '100' a double? " + isDouble("100")); // true
        System.out.println("Is '1.23e-5' a double? " + isDouble("1.23e-5")); // true
        System.out.println("Is 'hello' a double? " + isDouble("hello")); // false
    }
}

Using Integer.parseInt() and Double.parseDouble() to check for numeric strings.

Method 2: Using Regular Expressions (Regex)

Regular expressions offer a powerful and flexible way to define complex patterns for numeric strings. This method is excellent for enforcing specific formats (e.g., only positive integers, numbers with a fixed number of decimal places, or specific currency formats). While potentially more complex to write, regex can be very efficient once compiled.

import java.util.regex.Pattern;

public class RegexNumericCheck {

    // Pattern for integers (positive or negative)
    private static final Pattern INTEGER_PATTERN = Pattern.compile("-?\\d+");

    // Pattern for floating-point numbers (positive or negative, optional decimal part, optional scientific notation)
    private static final Pattern DOUBLE_PATTERN = Pattern.compile("-?(\\d+\\.?\\d*|\\.\\d+)([eE][-+]?\\d+)?");

    public static boolean isIntegerRegex(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        return INTEGER_PATTERN.matcher(str).matches();
    }

    public static boolean isDoubleRegex(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        return DOUBLE_PATTERN.matcher(str).matches();
    }

    public static void main(String[] args) {
        System.out.println("Is '123' an integer (regex)? " + isIntegerRegex("123")); // true
        System.out.println("Is '-45' an integer (regex)? " + isIntegerRegex("-45")); // true
        System.out.println("Is '123.45' an integer (regex)? " + isIntegerRegex("123.45")); // false
        System.out.println("Is 'abc' an integer (regex)? " + isIntegerRegex("abc")); // false

        System.out.println("\nIs '3.14' a double (regex)? " + isDoubleRegex("3.14")); // true
        System.out.println("Is '-0.5' a double (regex)? " + isDoubleRegex("-0.5")); // true
        System.out.println("Is '100' a double (regex)? " + isDoubleRegex("100")); // true
        System.out.println("Is '1.23e-5' a double (regex)? " + isDoubleRegex("1.23e-5")); // true
        System.out.println("Is 'hello' a double (regex)? " + isDoubleRegex("hello")); // false
        System.out.println("Is '.' a double (regex)? " + isDoubleRegex(".")); // false (needs at least one digit)
        System.out.println("Is '.5' a double (regex)? " + isDoubleRegex(".5")); // true
    }
}

Using regular expressions to validate numeric strings.

Method 3: Character-by-Character Check

For simple integer checks, iterating through the string and verifying each character can be an efficient approach, especially if you want to avoid exceptions or regex overhead. This method gives you fine-grained control over what characters are allowed.

public class CharByCharNumericCheck {

    public static boolean isPositiveInteger(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public static boolean isSignedInteger(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        int i = 0;
        if (str.charAt(0) == '-') {
            i = 1; // Skip the negative sign
            if (str.length() == 1) { // String is just "-"
                return false;
            }
        }
        for (; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println("Is '123' a positive integer? " + isPositiveInteger("123")); // true
        System.out.println("Is '-45' a positive integer? " + isPositiveInteger("-45")); // false
        System.out.println("Is 'abc' a positive integer? " + isPositiveInteger("abc")); // false

        System.out.println("\nIs '123' a signed integer? " + isSignedInteger("123")); // true
        System.out.println("Is '-45' a signed integer? " + isSignedInteger("-45")); // true
        System.out.println("Is '-' a signed integer? " + isSignedInteger("-")); // false
        System.out.println("Is '12.3' a signed integer? " + isSignedInteger("12.3")); // false
    }
}

Manual character-by-character check for integers.

Method 4: Using Apache Commons Lang's StringUtils.isNumeric()

If you're already using the Apache Commons Lang library in your project, it provides a convenient utility method StringUtils.isNumeric(). However, it's important to understand its definition of "numeric".

import org.apache.commons.lang3.StringUtils;

public class ApacheCommonsNumericCheck {

    public static void main(String[] args) {
        System.out.println("StringUtils.isNumeric('123'): " + StringUtils.isNumeric("123")); // true
        System.out.println("StringUtils.isNumeric('-123'): " + StringUtils.isNumeric("-123")); // false (doesn't allow sign)
        System.out.println("StringUtils.isNumeric('123.45'): " + StringUtils.isNumeric("123.45")); // false (doesn't allow decimal)
        System.out.println("StringUtils.isNumeric(''): " + StringUtils.isNumeric("")); // false
        System.out.println("StringUtils.isNumeric(null): " + StringUtils.isNumeric(null)); // false
        System.out.println("StringUtils.isNumeric(' '): " + StringUtils.isNumeric(" ")); // false
    }
}

Using Apache Commons Lang's StringUtils.isNumeric().

Performance Considerations

The performance of these methods can vary, especially when dealing with a large number of strings or very long strings:

  • Integer.parseInt() / Double.parseDouble(): Generally fast for valid numbers. Can be slower if many NumberFormatExceptions are thrown, as exception handling has overhead.
  • Regular Expressions: Compiling the pattern once (as shown with Pattern.compile()) makes subsequent matcher().matches() calls very efficient. Performance is good for complex patterns, but can be slower than simple character checks for very basic cases.
  • Character-by-Character: Often the fastest for simple integer checks as it avoids object creation and exception handling. However, it requires manual implementation for each numeric type.
  • Apache Commons Lang: Performance is comparable to its underlying implementation (e.g., isParsable() uses Double.parseDouble()).

For most applications, the performance difference is negligible. Prioritize readability and correctness unless profiling reveals a bottleneck.