Как лучше всего проверить, представляет ли String целое число в Java?

Обычно я использую следующую идиому, чтобы проверить, можно ли преобразовать String в целое число.

public boolean isInteger( String input ) {
    try {
        Integer.parseInt( input );
        return true;
    }
    catch( Exception e ) {
        return false;
    }
}

Это только мне кажется, или это кажется немного взломанным? Что лучше?


См. Мой ответ (с тестами, основанными на предыдущий ответ от CodingWithSpike), чтобы понять, почему я изменил свою позицию и принял Ответ Йонаса Клемминга для решения этой проблемы. Я думаю, что этот исходный код будет использоваться большинством людей, потому что его быстрее реализовать и легче поддерживать, но он на несколько порядков медленнее, когда предоставляются нецелочисленные данные.

Что вы думаете о RegExp для решения?

Akshay Pethani 27.02.2018 09:00
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
228
1
199 276
40
Перейти к ответу Данный вопрос помечен как решенный

Ответы 40

Как насчет:

return Pattern.matches("-?\\d+", input);

А как насчет целого числа 99999999999999999999999999999999?

danatel 26.10.2008 02:06

Не забудьте проверить наличие отрицательного знака.

Jeremy Ruten 26.10.2008 02:06

разве вам не нужно привязывать начало и конец регулярного выражения, чтобы вы не передавали "aaa-1999zzz"?

Tim Howland 26.10.2008 16:08

Тим, когда вы вызываете один из методов match () (каждый из которых имеет String, Pattern и Matcher), регулярное выражение должно соответствовать всему вводу, что делает якоря избыточными. Чтобы найти совпадение, как определено в большинстве других разновидностей регулярных выражений, вы должны использовать Matcher # find ().

Alan Moore 27.10.2008 08:23

Он у вас есть, но вы должны ловить только NumberFormatException.

Ага, ловить больше исключений, чем нужно, считается дурным тоном.

Chris 26.10.2008 04:28

Ты прав. NFE - единственное, что можно бросить, но это все еще плохая привычка.

Bill the Lizard 26.10.2008 06:26

Я думаю, что NPE может быть запущен, если input имеет значение null, поэтому ваш метод, вероятно, должен обрабатывать это явно, как вы хотите.

Dov Wasserman 26.10.2008 11:07

@Dov: Вы правы, NPE и NFE должны быть явно пойманы.

Bill the Lizard 26.10.2008 15:35

Этот ответ должен быть верным ответом на этот вопрос.

Breedly 10.02.2012 07:51

На мой взгляд, эта последовательность комментариев на самом деле представляет собой хороший случай, когда для ловит java.lang.Exception (или Throwable), демонстрируя, как очень легко пропустить один.

Reto Höhener 26.07.2013 10:35

Проголосуйте против, потому что перехват исключений противоположен коду для повышения производительности: P

rubdottocom 29.04.2014 19:06

Это короче, но короче не обязательно лучше (и он не будет улавливать целочисленные значения, выходящие за пределы диапазона, как указано в комментарии Данателя):

input.matches("^-?\\d+$");

Лично, поскольку реализация реализована во вспомогательном методе, а правильность превосходит длину, я бы просто выбрал что-то вроде того, что у вас есть (за вычетом базового класса Exception, а не NumberFormatException).

И, возможно, \\ d {1,10}, хотя и не идеальный, лучше, чем \\ d + для отлова целых чисел Java.

Maglob 26.10.2008 02:15

То, что вы сделали, работает, но вам, вероятно, не всегда следует так проверять. Выбрасывание исключений должно быть зарезервировано для «исключительных» ситуаций (хотя, возможно, это подходит для вашего случая), и это очень дорого с точки зрения производительности.

Они обходятся дорого только в том случае, если их бросают.

Bill the Lizard 26.10.2008 15:52
Ответ принят как подходящий

Если вас не беспокоят проблемы с переполнением, эта функция будет работать примерно в 20-30 раз быстрее, чем при использовании Integer.parseInt().

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    if (length == 0) {
        return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
        if (length == 1) {
            return false;
        }
        i = 1;
    }
    for (; i < length; i++) {
        char c = str.charAt(i);
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}

(c <= '/' || c> = ':') выглядит немного странно. Я бы использовал (c <'0' || c> '9') ... операторы <= и> = быстрее в Java?

Anonymous 26.10.2008 04:43

Почему бы не использовать регулярное выражение? Разве return str.matches ("^ -? \\ d + $") не идентичен приведенному выше коду.

Maglob 26.10.2008 12:28

Я бы использовал этот метод или исходный метод из вопроса перед регулярным выражением. Это для производительности, оригинальный метод для скорости внедрения и простой ремонтопригодности. Решение с регулярным выражением ничего не подходит.

Bill the Lizard 26.10.2008 16:19

Меня беспокоит переполнение, но этот метод можно адаптировать для BigInts и при этом он будет намного быстрее, чем другие методы. Если кому-то интересно, почему я вкладываю столько усилий в решение такой простой проблемы, я создаю библиотеку, чтобы помочь в решении проблем Project Euler.

Bill the Lizard 26.10.2008 16:25

Если вас беспокоит, действительно ли вы можете преобразовать строку в int или long, вам также нужно будет проверить, действительно ли целое число, которое представляет строка, соответствует этим типам данных.

Jonas K 29.09.2014 13:48

Обратите внимание, что эта функция намного быстрее, но, в конце концов, у вас нет целого числа! Если вы собираетесь использовать результат для фактического преобразования строки, прирост производительности не так важен, если ситуация «исключительная».

cquezel 12.05.2015 20:29

Разве это не вернет True, если str == "a123"?

Glen Pierce 13.05.2016 21:08

Как вы проверяете строки, начинающиеся с «0»?

Kcits 18.10.2016 17:11

@Bill: Не совсем верно, что решение с регулярным выражением ничего не подходит. Он использует класс \d, что позволяет избежать зависимостей как от цифровых символов (например, «0» и «9» против персидских цифр), так и от их порядка (сравнение <>). Эти зависимости на самом деле хрупкие, как вы увидите, когда появятся ваши целые числа, похожие на ۵۷۱۰. Регулярное выражение может действительно работать из коробки, если языковой стандарт установлен правильно.

LarsH 30.11.2016 09:47

Первые строки для проверки того, является ли "str" ​​нулевым или пустым, можно заменить на TextUtils.isEmpty (str). TextUtils является частью SDK и делает то же самое.

Herve Thu 05.12.2016 18:39

Зависит. "2.00" = 2? Для компьютеров обычно нет. Для математиков и людей, которые изучали математику в средней школе, да. Следовательно, приведенный выше ответ слабый. А как насчет «2»? или ".00"? Ниже вы узнаете, как справляться с подобными ситуациями.

Tihamer 02.07.2018 19:12

Как и в случае с любым методом фильтрации, если у вас небольшое количество ложных срабатываний, а само количество срабатываний намного меньше количества отрицательных ответов, вы всегда можете провести более полную проверку после быстрой проверки. (примечание - положительные = ответы с логическим результатом «истина»; отрицательные = ответы с логическим результатом «ложь»).

YoYo 28.03.2019 19:06

@Tihamer А как насчет научных обозначений? А как насчет восьмеричных или шестнадцатеричных чисел? А как насчет таких выражений, как 2 + 2, которое можно упростить до 4? И так далее. Этот ответ прекрасен, учитывая то, что он решает (простые целочисленные значения без учета переполнения).

Guildenstern 22.06.2020 19:06

когда ввод - это один единственный оператор, такой как "*", функция также вернет true ...

Yossarian42 29.07.2020 00:16
Integer.valueOf(string); 

у меня работает большую часть времени!

Это (все - большую часть) времени меня беспокоит. :)

Bill the Lizard 26.10.2008 16:22

Сделал быстрый тест. На самом деле исключения не так уж и дороги, если только вы не начнете возвращать несколько методов, и JVM придется проделать большую работу, чтобы установить стек выполнения. Если придерживаться того же метода, они неплохие исполнители.

 public void RunTests()
 {
     String str = "1234567890";

     long startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByException(str);
     long endTime = System.currentTimeMillis();
     System.out.print("ByException: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByRegex(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByRegex: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByJonas(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByJonas: ");
     System.out.println(endTime - startTime);
 }

 private boolean IsInt_ByException(String str)
 {
     try
     {
         Integer.parseInt(str);
         return true;
     }
     catch(NumberFormatException nfe)
     {
         return false;
     }
 }

 private boolean IsInt_ByRegex(String str)
 {
     return str.matches("^-?\\d+$");
 }

 public boolean IsInt_ByJonas(String str)
 {
     if (str == null) {
             return false;
     }
     int length = str.length();
     if (length == 0) {
             return false;
     }
     int i = 0;
     if (str.charAt(0) == '-') {
             if (length == 1) {
                     return false;
             }
             i = 1;
     }
     for (; i < length; i++) {
             char c = str.charAt(i);
             if (c <= '/' || c >= ':') {
                     return false;
             }
     }
     return true;
 }

Выход:

ByException: 31

ByRegex: 453 (note: re-compiling the pattern every time)

ByJonas: 16

Я согласен с тем, что решение Йонаса К. также является самым надежным. Похоже, он выигрывает :)

Отличная идея протестировать все три. Чтобы быть справедливым по отношению к методам Regex и Jonas, вы должны тестировать нецелочисленные строки, поскольку именно там метод Integer.parseInt действительно замедлится.

Bill the Lizard 26.10.2008 16:00

Извините, но этот тест с регулярным выражением не подходит. (1) Вам не нужно выполнять проверку движка регулярных выражений для ^ и $ второй раз, поскольку в matches вся строка должна соответствовать регулярному выражению, (2) str.matches каждый раз должен будет создавать свой собственный Pattern, что дорого. По соображениям производительности мы должны создать такой Pattern только один раз вне этого метода и использовать его внутри. (3) Мы также можем создать только один объект Matcher и использовать его reset(CharSequence) для передачи пользовательских данных и возврата результата matches().

Pshemo 06.11.2013 19:01

Так что что-то вроде private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); } должно иметь лучшую производительность.

Pshemo 06.11.2013 19:02

@Pshemo Integer.valueOf ("1") и Integer.valueOf ("1") генерируют исключение, поэтому проверка на ^ и $ кажется разумной.

cquezel 12.05.2015 20:33

@cquezel Да, но это не требуется, поскольку matches неявно добавляет ^ и $. Взгляните на результат " 123".matches("\\d+") и "123".matches("\\d+"). Вы увидите false и true. false будет возвращен, потому что строка начинается с пробела, что предотвращает полное совпадение с регулярным выражением.

Pshemo 12.05.2015 21:07

Вы также можете использовать класс Сканер и использовать hasNextInt () - и это позволяет вам тестировать и другие типы, такие как поплавки и т. д.

Этот ответ напомнил мне, что мне нужно. Я совсем забыл, что у Сканера есть такая функция. Футболка

Hubro 26.10.2010 18:15

Отчасти это зависит от того, что вы имеете в виду под «может быть преобразовано в целое число».

Если вы имеете в виду «можно преобразовать в int в Java», то ответ Джонаса - хорошее начало, но не совсем завершение работы. Например, он будет проходить 999999999999999999999999999999. Я бы добавил обычный вызов try / catch из вашего собственного вопроса в конце метода.

Посимвольные проверки будут эффективно отклонять случаи «вообще не целое число», оставляя случаи «это целое число, но Java не может его обработать», которые будут перехвачены более медленным маршрутом исключения. Вы, мог, тоже делаете это вручную, но это будет более сложный много.

Number number;
try {
    number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
    //not a number - do recovery.
    e.printStackTrace();
}
//use number

Всего один комментарий о регулярном выражении. Каждый приведенный здесь пример неверен !. Если вы хотите использовать регулярное выражение, не забывайте, что компиляция шаблона занимает много времени. Этот:

str.matches("^-?\\d+$")

а также это:

Pattern.matches("-?\\d+", input);

вызывает компиляцию шаблона при каждом вызове метода. Для правильного использования выполните следующие действия:

import java.util.regex.Pattern;

/**
 * @author Rastislav Komara
 */
public class NaturalNumberChecker {
    public static final Pattern PATTERN = Pattern.compile("^\\d+$");

    boolean isNaturalNumber(CharSequence input) {
        return input != null && PATTERN.matcher(input).matches();
    }
}

Вы можете добиться немного большей производительности, заранее создав Matcher и применив его метод reset () к входным данным.

Alan Moore 27.10.2008 08:43

Я скопировал код из ответа rally25rs и добавил несколько тестов для нецелочисленных данных. Результаты, несомненно, свидетельствуют в пользу метода, опубликованного Йонасом Клеммингом. Результаты для метода Exception, который я изначально опубликовал, довольно хороши, когда у вас есть целочисленные данные, но они худшие, когда у вас их нет, в то время как результаты для решения RegEx (которое, я уверен, многие люди используют) были последовательно плохими. См. Ответ Фелипе для примера скомпилированного регулярного выражения, который намного быстрее.

public void runTests()
{
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Полученные результаты:

ByException - integer data: 47
ByException - non-integer data: 547

ByRegex - integer data: 390
ByRegex - non-integer data: 313

ByJonas - integer data: 0
ByJonas - non-integer data: 16
org.apache.commons.lang.StringUtils.isNumeric 

хотя стандартная библиотека Java действительно пропускает такие служебные функции

Я считаю, что Apache Commons просто необходим каждому программисту на Java.

жаль, что он еще не портирован на Java5

Единственная проблема с этим - переполнение: S Я все еще даю вам +1 за упоминание commons-lang :)

javamonkey79 28.07.2010 03:55

Другая проблема - отрицательные числа, но я также +1, поскольку, на мой взгляд, этот подход ближе всего к хорошему решению.

sandris 09.01.2013 11:38

Поскольку есть вероятность, что люди все еще будут сюда заходить и будут предвзято относиться к Regex после тестов ... Итак, я дам обновленную версию теста с скомпилированной версией Regex. В отличие от предыдущих тестов, этот показывает, что решение Regex действительно имеет стабильно хорошую производительность.

Скопировано из Bill the Lizard и обновлено скомпилированной версией:

private final Pattern pattern = Pattern.compile("^-?\\d+$");

public void runTests() {
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByCompiledRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByCompiledRegex - non-integer data: ");
    System.out.println(endTime - startTime);


    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

private boolean IsInt_ByCompiledRegex(String str) {
    return pattern.matcher(str).find();
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Полученные результаты:

ByException - integer data: 45
ByException - non-integer data: 465

ByRegex - integer data: 272
ByRegex - non-integer data: 131

ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26

ByJonas - integer data: 8
ByJonas - non-integer data: 2

Время ByCompiledRegex должно включать компиляцию регулярного выражения в его измерение времени.

Martin 24.12.2013 00:53

@MartinCarney Я модифицировал его и протестировал компиляцию паттернов. Очевидно, мой CPU / JIT быстрее, но если я интерполирую его обратно, время компиляции будет 336.

tedder42 09.10.2014 03:26

Чтобы было ясно, что 336 (мс) - это то, что происходит, когда компиляция шаблона выполняется 100k раз, как и все другие строки. Подразумевая, что это делается только один раз, его время в основном равно нулю.

tedder42 09.10.2014 03:50

Спасибо, что установили рекорд времени скомпилированного регулярного выражения.

LarsH 30.11.2016 09:50

Может быть, "^[+-]?\\d+$" был бы даже лучше.

Adam 15.05.2017 13:54

Это будет работать только для положительных целых чисел.

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

Добро пожаловать в stackoverflow. Перед тем, как воскресить старую ветку, обязательно прочтите предыдущие ответы и комментарии. Этот метод (и возможные недостатки) фактически уже обсуждался.

Leigh 31.03.2012 04:20

Вероятно, вам также нужно принять во внимание вариант использования:

Если в большинстве случаев вы ожидаете, что числа будут действительными, то перехват исключения приводит только к снижению производительности при попытке преобразовать недопустимые числа. В то время как вызов некоторого метода isInteger() и последующее преобразование с использованием Integer.parseInt() приведет к увеличению производительности всегда для действительных чисел - строки анализируются дважды, один раз проверкой и один раз преобразованием.

Вы можете использовать метод совпадений строкового класса. [0-9] представляет все возможные значения, + означает, что он должен состоять как минимум из одного символа, а * означает, что он может содержать ноль или более символов.

boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only

Nb, это не соответствует "+10" или "-10"), которые обычно включаются как действительные целые числа.

Tim Wintle 27.04.2015 18:05

Просто проверьте NumberFormatException: -

 String value = "123";
 try  
 {  
    int s=Integer.parseInt(any_int_val);
    // do something when integer values comes 
 }  
 catch(NumberFormatException nfe)  
 {  
          // do something when string values comes 
 }  

Вы можете попробовать apache utils

NumberUtils.isCreatable(myText)

См. Javadoc здесь

Похоже, этот метод устарел в последней версии связь). По-видимому, вам следует использовать вместо этого isCreateable(String).

Guildenstern 19.06.2020 14:36

Обновлено. Спасибо @Guildenstern

borjab 19.06.2020 15:23

Если ваш массив String содержит чистые целые числа и строки, приведенный ниже код должен работать. Вам нужно только посмотреть на первого персонажа. например [«4», «44», «abc», «77», «облигация»]

if (Character.isDigit(string.charAt(0))) {
    //Do something with int
}

Для тех читателей, которые приходят сюда, как и я, спустя годы после того, как вопрос был задан, у меня есть более общее решение этого вопроса.

/**
 * Checks, if the string represents a number.
 *
 * @param string the string
 * @return true, if the string is a number
 */
public static boolean isANumber(final String string) {
    if (string != null) {
        final int length = string.length();
        if (length != 0) {
            int i = 0;
            if (string.charAt(0) == '-') {
                if (length == 1) {
                    return false;
                }
                i++;
            }
            for (; i < length; i++) {
                final char c = string.charAt(i);
                if ((c <= PERIOD) || ((c >= COLON))) {
                    final String strC = Character.toString(c).toUpperCase();
                    final boolean isExponent = strC.equals("E");
                    final boolean isPeriod = (c == PERIOD);
                    final boolean isPlus = (c == PLUS);

                    if (!isExponent && !isPeriod && !isPlus) {
                        return false;
                    }
                }
            }
            return true;
        }
    }
    return false;
}

Try / catch предназначен для использования, когда вы действительно не контролируете, что может пойти не так. В этом случае - можете, и принятый ответ по-прежнему остается хорошим решением. Кроме того, создание исключений обходится дорого, и этого следует избегать.

ılǝ 27.05.2014 11:23

Это модификация кода Йонас ', которая проверяет, находится ли строка в пределах диапазона, который нужно преобразовать в целое число.

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    int i = 0;

    // set the length and value for highest positive int or lowest negative int
    int maxlength = 10;
    String maxnum = String.valueOf(Integer.MAX_VALUE);
    if (str.charAt(0) == '-') { 
        maxlength = 11;
        i = 1;
        maxnum = String.valueOf(Integer.MIN_VALUE);
    }  

    // verify digit length does not exceed int range
    if (length > maxlength) { 
        return false; 
    }

    // verify that all characters are numbers
    if (maxlength == 11 && length == 1) {
        return false;
    }
    for (int num = i; num < length; num++) {
        char c = str.charAt(num);
        if (c < '0' || c > '9') {
            return false;
        }
    }

    // verify that number value is within int range
    if (length == maxlength) {
        for (; i < length; i++) {
            if (str.charAt(i) < maxnum.charAt(i)) {
                return true;
            }
            else if (str.charAt(i) > maxnum.charAt(i)) {
                return false;
            }
        }
    }
    return true;
}

выглядит хорошо, но в последнем цикле for необходимо сбросить i до нуля (или 1, если число отрицательное), потому что цикл, который проверяет, является ли каждая цифра числом, приведет к тому, что i будет длиной строки, поэтому последний цикл for никогда не побегу. Я бы также использовал константы Java Integer.MAX_VALUE и Integer.MIN_VALUE вместо магических чисел.

Tim the Enchanter 21.08.2014 19:42

@TimtheEnchanter Спасибо за предложения, я их полностью упустил. В моем редактировании, чтобы включить их, я использовал новую переменную в первом цикле for, чтобы избежать лишнего оператора if.

Wayne 21.08.2014 20:47

У меня это работает. Просто чтобы определить, является ли String примитивом или числом.

private boolean isPrimitive(String value){
        boolean status=true;
        if (value.length()<1)
            return false;
        for(int i = 0;i<value.length();i++){
            char c=value.charAt(i);
            if (Character.isDigit(c) || c=='.'){

            }else{
                status=false;
                break;
            }
        }
        return status;
    }

Чтобы проверить все символы int, вы можете просто использовать двойное отрицание.

если (! searchString.matches ("[^ 0-9] + $")) ...

[^ 0-9] + $ проверяет, есть ли какие-либо символы, которые не являются целыми числами, поэтому тест не выполняется, если это правда. Только НЕ это, и вы получите правду в случае успеха.

Нет. Вы явно не проверяли это. Это возвращает истину, только если где-то в строке есть цифра, а не если строка состоит только из цифр. Метод matches сопоставляется со всей строкой, а не только с ее частью.

Dawood ibn Kareem 22.07.2018 23:02

Вы не получите двойной отрицательной части.

Roger F. Gay 24.07.2018 01:28

Ну, я НЕ получаю двойного негатива. Это просто не работает. Если у вас есть смесь цифр и букв, они попадают в блок if. Не должно.

Dawood ibn Kareem 24.07.2018 02:21

Я считаю, что нет никакого риска столкнуться с исключением, потому что, как вы можете видеть ниже, вы всегда безопасно разбираете int в String, а не наоборот.

Так:

  1. Вы контрольный, если каждый слот символа в вашей строке соответствует хотя бы один из символов {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}.

    if (aString.substring(j, j+1).equals(String.valueOf(i)))
    
  2. Вы сумма все раз, когда сталкивались в слотах выше символы.

    digits++;
    
  3. И, наконец, вы контрольный, если времена, когда вы встречали целые числа как символов равно длине данной строки.

    if (digits == aString.length())
    

А на практике имеем:

    String aString = "1234224245";
    int digits = 0;//count how many digits you encountered
    for(int j=0;j<aString.length();j++){
        for(int i=0;i<=9;i++){
            if (aString.substring(j, j+1).equals(String.valueOf(i)))
                    digits++;
        }
    }
    if (digits == aString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }
    
    String anotherString = "1234f22a4245";
    int anotherDigits = 0;//count how many digits you encountered
    for(int j=0;j<anotherString.length();j++){
        for(int i=0;i<=9;i++){
            if (anotherString.substring(j, j+1).equals(String.valueOf(i)))
                    anotherDigits++;
        }
    }
    if (anotherDigits == anotherString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }

И вот результаты:

It's an integer!!

It's not an integer!!

Точно так же вы можете проверить, является ли Stringfloat или double, но в этих случаях вы должны встретить только один . (точка) в строке и, конечно, проверить, является ли digits == (aString.length()-1)

Again, there's zero risk running into a parsing exception here, but if you plan on parsing a string that it is known that contains a number (let's say int data type) you must first check if it fits in the data type. Otherwise you must cast it.

Надеюсь я помог

Это может быть полезно:

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}

Если вы используете Android API, вы можете использовать:

TextUtils.isDigitsOnly(str);

Есть версия гуавы:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Он вернет значение null вместо того, чтобы генерировать исключение, если не удалось проанализировать строку.

Лучший ответ ИМХО. Используйте хорошо протестированные библиотеки вместо того, чтобы создавать собственное решение. (Также см. Обсуждение здесь.)

Olivier Cailloux 25.08.2017 14:47
public class HelloWorld{

    static boolean validateIP(String s){
        String[] value = s.split("\\.");
        if (value.length!=4) return false;
        int[] v = new int[4];
        for(int i=0;i<4;i++){
            for(int j=0;j<value[i].length();j++){
                if (!Character.isDigit(value[i].charAt(j))) 
                 return false;
            }
            v[i]=Integer.parseInt(value[i]);
            if (!(v[i]>=0 && v[i]<=255)) return false;
        }
        return true;
    }

    public static void main(String[] argv){
        String test = "12.23.8.9j";
        if (validateIP(test)){
            System.out.println(""+test);
        }
    }
}

При чем тут IP-адрес?

Guildenstern 22.06.2020 19:54

Другой вариант:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}

Я видел здесь много ответов, но большинство из них могут определить, является ли String числовым, но они не проверяют, находится ли число в целочисленном диапазоне ...

Поэтому я намерен сделать что-то вроде этого:

public static boolean isInteger(String str) {
    if (str == null || str.isEmpty()) {
        return false;
    }
    try {
        long value = Long.valueOf(str);
        return value >= -2147483648 && value <= 2147483647;
    } catch (Exception ex) {
        return false;
    }
}

Хороший момент, обрабатывается com.google.common.primitives.Ints.tryParse (String, int), предложенным в ответе Guava.

Adrian Baker 16.01.2017 11:03

Но у строкового значения тоже есть шанс выйти за пределы длинного лимита. Как мы можем предположить, что это далеко. Например, строка также может содержать это значение 9 223 372 036 854 775 809, но long не может, и в этом случае мы получаем исключение NumberFormatException.

srinivas 06.12.2019 06:45

Метод должен проверить, находится ли значение, представленное String, в диапазоне Integer. Если вы предоставите методу аргумент, который даже больше, чем Long, то это определенно не целое число, и метод должен вернуть «false». Что и происходит, поскольку при преобразовании возникает ошибка, а в предложении catch указывается значение false.

Ellrohir 13.12.2019 18:15

Это вариант Java 8 ответа Джонаса Клемминга:

public static boolean isInteger(String str) {
    return str != null && str.length() > 0 &&
         IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
                  || Character.isDigit(str.charAt(i)));
}

Код теста:

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
            "123-23", null, "+-123").forEach(s -> {
        System.out.printf("%15s %s%n", s, isInteger(s));
    });
}

Результаты теста кода:

        1231231 true
    -1232312312 true
   +12313123131 true
  qwqe123123211 false
              2 true
  0000000001111 true
                false
           123- false
          ++123 false
         123-23 false
           null false
          +-123 false

Если вы хотите проверить, представляет ли строка целое число, подходящее для типа int, я немного изменил ответ jonas, чтобы строки, представляющие целые числа больше Integer.MAX_VALUE или меньше Integer.MIN_VALUE, теперь возвращали ложный. Например: «3147483647» вернет false, потому что 3147483647 больше, чем 2147483647, и аналогично «-2147483649» также вернет false, потому что -2147483649 меньше, чем -2147483648.

public static boolean isInt(String s) {
  if (s == null) {
    return false;
  }
  s = s.trim(); //Don't get tricked by whitespaces.
  int len = s.length();
  if (len == 0) {
    return false;
  }
  //The bottom limit of an int is -2147483648 which is 11 chars long.
  //[note that the upper limit (2147483647) is only 10 chars long]
  //Thus any string with more than 11 chars, even if represents a valid integer, 
  //it won't fit in an int.
  if (len > 11) {
    return false;
  }
  char c = s.charAt(0);
  int i = 0;
  //I don't mind the plus sign, so "+13" will return true.
  if (c == '-' || c == '+') {
    //A single "+" or "-" is not a valid integer.
    if (len == 1) {
      return false;
    }
    i = 1;
  }
  //Check if all chars are digits
  for(; i < len; i++) {
    c = s.charAt(i);
    if (c < '0' || c > '9') {
      return false;
    }
  }
  //If we reached this point then we know for sure that the string has at
  //most 11 chars and that they're all digits (the first one might be a '+'
  // or '-' thought).
  //Now we just need to check, for 10 and 11 chars long strings, if the numbers
  //represented by the them don't surpass the limits.
  c = s.charAt(0);
  char l;
  String limit;
  if (len == 10 && c != '-' && c != '+') {
    limit = "2147483647";
    //Now we are going to compare each char of the string with the char in
    //the limit string that has the same index, so if the string is "ABC" and
    //the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
    //c is the current string's char and l is the corresponding limit's char
    //Note that the loop only continues if c == l. Now imagine that our string
    //is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
    //because 5 > 4 we can guarantee that the string will represent a bigger integer.
    //Similarly, if our string was "2139999999", when we find out that 3 < 4,
    //we can also guarantee that the integer represented will fit in an int.
    for(i = 0; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if (c > l) {
        return false;
      }
      if (c < l) {
        return true;
      }
    }
  }
  c = s.charAt(0);
  if (len == 11) {
    //If the first char is neither '+' nor '-' then 11 digits represent a 
    //bigger integer than 2147483647 (10 digits).
    if (c != '+' && c != '-') {
      return false;
    }
    limit = (c == '-') ? "-2147483648" : "+2147483647";
    //Here we're applying the same logic that we applied in the previous case
    //ignoring the first char.
    for(i = 1; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if (c > l) {
        return false;
      }
      if (c < l) {
        return true;
      }
    }
  }
  //The string passed all tests, so it must represent a number that fits
  //in an int...
  return true;
}

не могли бы вы отредактировать свой ответ и объяснить, как он улучшает предыдущий ответ, который вы упомянули?

Gilles Gouaillardet 25.08.2017 05:26

Спасибо за отличный ответ. Но «123», то есть 123 вместе с пробелом, считается действительным целым числом.

Saikrishna Radarapu 20.04.2018 11:37

@SaikrishnaRadarapu Они используют trim(), так что это явно намеренный выбор дизайна.

Guildenstern 21.06.2020 01:08

Когда объяснения важнее производительности

Я заметил много дискуссий о том, насколько эффективны определенные решения, но в Почему ни одна строка не является целым числом. Кроме того, все, казалось, полагали, что число «2,00» не равно «2». С математической и человеческой точки зрения они равны являются (хотя компьютерные науки говорят, что это не так, и не зря). Вот почему решения "Integer.parseInt" выше слабые (в зависимости от ваших требований).

В любом случае, чтобы сделать программное обеспечение более умным и удобным для человека, нам нужно создать программное обеспечение, которое думает так же, как мы, и объясняет Почему, что что-то не удалось. В этом случае:

public static boolean isIntegerFromDecimalString(String possibleInteger) {
possibleInteger = possibleInteger.trim();
try {
    // Integer parsing works great for "regular" integers like 42 or 13.
    int num = Integer.parseInt(possibleInteger);
    System.out.println("The possibleInteger = "+possibleInteger+" is a pure integer.");
    return true;
} catch (NumberFormatException e) {
    if (possibleInteger.equals(".")) {
        System.out.println("The possibleInteger = " + possibleInteger + " is NOT an integer because it is only a decimal point.");
        return false;
    } else if (possibleInteger.startsWith(".") && possibleInteger.matches("\\.[0-9]*")) {
        if (possibleInteger.matches("\\.[0]*")) {
            System.out.println("The possibleInteger = " + possibleInteger + " is an integer because it starts with a decimal point and afterwards is all zeros.");
            return true;
        } else {
            System.out.println("The possibleInteger = " + possibleInteger + " is NOT an integer because it starts with a decimal point and afterwards is not all zeros.");
            return false;
        }
    } else if (possibleInteger.endsWith(".")  && possibleInteger.matches("[0-9]*\\.")) {
        System.out.println("The possibleInteger = "+possibleInteger+" is an impure integer (ends with decimal point).");
        return true;
    } else if (possibleInteger.contains(".")) {
        String[] partsOfPossibleInteger = possibleInteger.split("\\.");
        if (partsOfPossibleInteger.length == 2) {
            //System.out.println("The possibleInteger = " + possibleInteger + " is split into '" + partsOfPossibleInteger[0] + "' and '" + partsOfPossibleInteger[1] + "'.");
            if (partsOfPossibleInteger[0].matches("[0-9]*")) {
                if (partsOfPossibleInteger[1].matches("[0]*")) {
                    System.out.println("The possibleInteger = "+possibleInteger+" is an impure integer (ends with all zeros after the decimal point).");
                    return true;
                } else if (partsOfPossibleInteger[1].matches("[0-9]*")) {
                    System.out.println("The possibleInteger = " + possibleInteger + " is NOT an integer because it the numbers after the decimal point (" + 
                                partsOfPossibleInteger[1] + ") are not all zeros.");
                    return false;
                } else {
                    System.out.println("The possibleInteger = " + possibleInteger + " is NOT an integer because it the 'numbers' after the decimal point (" + 
                            partsOfPossibleInteger[1] + ") are not all numeric digits.");
                    return false;
                }
            } else {
                System.out.println("The possibleInteger = " + possibleInteger + " is NOT an integer because it the 'number' before the decimal point (" + 
                        partsOfPossibleInteger[0] + ") is not a number.");
                return false;
            }
        } else {
            System.out.println("The possibleInteger = "+possibleInteger+" is NOT an integer because it has a strange number of decimal-period separated parts (" +
                    partsOfPossibleInteger.length + ").");
            return false;
        }
    } // else
    System.out.println("The possibleInteger='"+possibleInteger+"' is NOT an integer, even though it has no decimal point.");
    return false;
}
}

Код теста:

String[] testData = {"0", "0.", "0.0", ".000", "2", "2.", "2.0", "2.0000", "3.14159", ".0001", ".", "$4.0", "3E24", "6.0221409e+23"};
int i = 0;
for (String possibleInteger : testData ) {
    System.out.println("");
    System.out.println(i + ". possibleInteger='" + possibleInteger +"' isIntegerFromDecimalString = " + isIntegerFromDecimalString(possibleInteger));
    i++;
}

Я думаю, что ваше объяснение проливает свет на ситуации, о которых люди, честно говоря, не думали, и позволило бы создать гораздо более надежный код. Однако вы предполагаете, что мы используем точку (.) В качестве разделителя. Это не касается удобочитаемости вводимых данных, таких как: разделитель тысяч, бухгалтерские скобки, другое основание или использование арабских чисел. Также нет причин генерировать исключение в этом методе, поскольку мы знаем каждое состояние, в котором должна находиться эта строка, учитывая ее неизменное состояние, и мы собираемся быть хорошими программистами и изменять ссылку - дальнейшее чтение wiki.c2.com/?ExceptionPatterns

David Fisher 21.11.2019 14:30

Дэвид - вы абсолютно правы; особенно о разделителе тысяч запятых (что важно для удобочитаемости). Для действительно общего решения нам нужно будет принять во внимание все предположения - хотя я вполне уверен, что не так много людей используют неарабские числа. :-)

Tihamer 22.11.2019 17:06

Мне не нравится метод с регулярным выражением, потому что регулярное выражение не может проверять диапазоны (Integer.MIN_VALUE, Integer.MAX_VALUE).

Если вы в большинстве случаев ожидаете значение int, а не int - что-то необычное, то я предлагаю версию с Integer.valueOf или Integer.parseInt с перехватом NumberFormatException. Преимущество такого подхода - ваш код хорошо читается:

public static boolean isInt(String s) {
  try {
    Integer.parseInt(s);
    return true;
  } catch (NumberFormatException nfe) {
    return false;
  }
}

Если вам нужно проверить, является ли String целочисленным, и позаботиться о производительности, тогда лучшим способом будет использовать java jdk-реализацию Integer.parseInt, но немного измененную (заменив throw на return false):

Эта функция имеет хорошую производительность и гарантирует правильный результат:

   public static boolean isInt(String s) {
    int radix = 10;

    if (s == null) {
        return false;
    }

    if (radix < Character.MIN_RADIX) {
        return false;
    }

    if (radix > Character.MAX_RADIX) {
        return false;
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < '0') { // Possible leading "+" or "-"
            if (firstChar == '-') {
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if (firstChar != '+')
                return false;

            if (len == 1) // Cannot have lone "+" or "-"
                return false;
            i++;
        }
        multmin = limit / radix;
        while (i < len) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++), radix);
            if (digit < 0) {
                return false;
            }
            if (result < multmin) {
                return false;
            }
            result *= radix;
            if (result < limit + digit) {
                return false;
            }
            result -= digit;
        }
    } else {
        return false;
    }
    return true;
}

Ты мог бы:

  1. Убедитесь, что строка является числом
  2. Убедитесь, что он не слишком длинный, чтобы его можно было разобрать как long.
  3. Убедитесь, что полученное значение long достаточно мало, чтобы его можно было представить как int.

(Предполагая, что вам по какой-то причине придется реализовать это самостоятельно: вам, вероятно, сначала следует взглянуть на com.google.common.primitives.Ints.tryParse(String) и посмотреть, достаточно ли он для ваших целей (как предлагается в другом ответе).)

// Credit to Rastislav Komara’s answer: https://stackoverflow.com/a/237895/1725151
private static final Pattern nonZero = Pattern.compile("^-?[1-9]\\d*$");

// See if `str` can be parsed as an `int` (does not trim)
// Strings like `0023` are rejected (leading zeros).
public static boolean parsableAsInt(@Nonnull String str) {
    if (str.isEmpty()) {
        return false;
    }
    if (str.equals("0")) {
        return true;
    }
    if (canParseAsLong(str)) {
        long value = Long.valueOf(str);
        if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
            return true;
        }
    }
    return false;
}

private static boolean canParseAsLong(String str) {
    final int intMaxLength = 11;
    return str.length() <= intMaxLength && nonZero.matcher(str).matches();
}

Этот метод также можно преобразовать для возврата Optional<Integer>, чтобы вам не приходилось дважды анализировать строку в клиентском коде (один раз, чтобы проверить, возможно ли это, а второй раз сделать это «по-настоящему»). Например:

if (canParseAsLong(str)) {
    long value = Long.valueOf(str);
    if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
        return Optional.of((int) value);
    }
}

небольшое улучшение @Jonas K anwser, эта функция исключит один единственный оператор, такой как "*".

public boolean isInteger(String str) {
    // null pointer
    if (str == null) {
        return false;
    }
    int len = str.length();
    // empty string
    if (len == 0) {
        return false;
    }
    // one digit, cannot begin with 0
    if (len == 1) {
        char c = str.charAt(0);
        if ((c < '1') || (c > '9')) {
            return false;
        }
    }

    for (int i = 0; i < len; i++) {
        char c = str.charAt(i);
        // check positive, negative sign
        if (i == 0) {
            if (c == '-' || c == '+') {
                continue;
            }
        }
        // check each character matches [0-9]
        if ((c < '0') || (c > '9')) {
            return false;
        }
    }
    return true;
}

Мне недавно (сегодня) нужно было найти быстрый способ сделать это, и, конечно, я собирался использовать подход исключения для облегчения, когда обезьяна на плече (совесть) проснулась, поэтому она унесла меня в эту старую знакомую кроличью нору; никакие исключения не намного дороже, на самом деле иногда исключения быстрее (старые многопроцессорные системы AIX), но, несмотря на то, что это слишком элегантно, поэтому я сделал то, чего никогда не делал младший я, и, к моему удивлению, никто здесь тоже не делал (извиняюсь, если кто-то это сделал, и я пропустил я, честно говоря, не нашел): так что я думаю мы все упустили; взглянув на то, как это реализовано в JRE, да, они выдали исключение, но мы всегда можем пропустить эту часть.

Младший я из 10 лет назад чувствовал бы, что это ниже его, но опять же, он громкий хвастун с плохим темпераментом и комплексом бога, так что это есть.

Я помещаю это здесь на благо всех, кто придет сюда в будущем. Вот что я нашел:

public static int parseInt(String s, int radix) throws NumberFormatException
{
    /*
     * WARNING: This method may be invoked early during VM initialization
     * before IntegerCache is initialized. Care must be taken to not use
     * the valueOf method.
     */

    if (s == null) {
        throw new NumberFormatException("null");
    }

    if (radix < Character.MIN_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " less than Character.MIN_RADIX");
    }

    if (radix > Character.MAX_RADIX) {
        throw new NumberFormatException("radix " + radix +
                                        " greater than Character.MAX_RADIX");
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < '0') { // Possible leading "+" or "-"
            if (firstChar == '-') {
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if (firstChar != '+')
                throw NumberFormatException.forInputString(s);

            if (len == 1) // Cannot have lone "+" or "-"
                throw NumberFormatException.forInputString(s);
            i++;
        }
        multmin = limit / radix;
        while (i < len) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            if (result < multmin) {
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            if (result < limit + digit) {
                throw NumberFormatException.forInputString(s);
            }
            result -= digit;
        }
    } else {
        throw NumberFormatException.forInputString(s);
    }
    return negative ? result : -result;
}

несколько ответов здесь, в которых говорится, что нужно попробовать разобрать целое число и поймать NumberFormatException, но вы не должны этого делать.

Таким образом будет создан объект исключения и будет генерироваться трассировка стека каждый раз, когда вы его вызываете, и это не целое число.

Лучшим способом с Java 8 было бы использовать поток:

boolean isInteger = returnValue.chars().allMatch(Character::isDigit);

Для Котлин, isDigitsOnly()(Также для Java TextUtils.isDigitsOnly()) из String всегда возвращает false, перед ним стоит отрицательный знак, хотя остальная часть символа является только цифрой. Например -

/** For kotlin*/
var str = "-123" 
str.isDigitsOnly()  //Result will be false 

/** For Java */
String str = "-123"
TextUtils.isDigitsOnly(str) //Result will be also false 

Итак, я быстро исправил это -

 var isDigit=str.matches("-?\\d+(\\.\\d+)?".toRegex()) 
/** Result will be true for now*/

Другие вопросы по теме