Преобразование String в integers безопасным способом

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


Версия A: просто оставьте это как есть и возьмите на себя риски (которых я пытаюсь избежать)

public static int stringToInt(String param) {
        return Integer.valueOf(param);
}

(с точки зрения скорости, какая разница в версии B и C?)


Версия B: выхватить исключение

public static int stringToInt(String param) {
        try {
                return Integer.valueOf(param);
        } catch(NumberFormatException e) {
                return -1;
        }
}

Версия C: проверьте каждую букву строки, чтобы увидеть ее, если это цифра или нет

public static int stringToInt(String param) {
        for(char c : param.toCharArray()) {
                if(!Character.isDigit(c))
                        return -1;
        }
        return Integer.valueOf(param);
}

Обратите внимание, что параметр должен быть положительным числом, а значение -1 должно быть "значением ошибки" в моей маленькой программе, другими словами, все три версии методов будут отлично работать в моей программе.

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

Благодарим вас за поддержку.

Ответ 1

Во-первых, обратите внимание, что версия C не является пуленепробиваемой: она будет отклонять отрицательные числа и не будет ловить слишком большие числа.

Версия B в порядке, но при этом вызывающий абонент меняет стиль кодирования: вместо того, чтобы ловить ошибку и обрабатывать ее вместе с другими ошибками, вызывающему абоненту нужно будет постоянно проверять -1. Это может быть субоптимальным в ситуациях, когда вы читаете несколько целых чисел, но обработка ошибок не зависит от того, какой из них был неудачным. Кроме того, новые кодеры, использующие ваш API, могут забыть проверить -1 и непреднамеренно использовать код ошибки.

Вот почему я останусь с первым вариантом: код, использующий версию A, сразу же будет знаком любому, кто знает Java API, без необходимости узнавать, что происходит внутри вашей функции.

Ответ 2

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

https://google.github.io/guava/releases/19.0/api/docs/com/google/common/primitives/Ints.html#tryParse(java.lang.String)

Integer result = Ints.tryParse("1");  //returns 1
Integer result = Ints.tryParse("-1"); //returns -1
Integer result = Ints.tryParse("a");  //returns null

Ответ 3

Я полагаю, что лучшим вариантом будет модифицированный B, чтобы исключить исключение, а не возвращать -1. Хорошо исключить исключение до уровня, где его можно обработать, чтобы отправить правильный ответ пользователю. Возврат значения, равного -1, сделает вашу ошибку кода неприемлемой. Предположим, что другой программист использует ваш метод, и он/она просто имеет подпись вашего метода. Поэтому из подписи неясно, что он/она должен кодировать для обработки сценария исключения или ошибки. Но если вы выбросите исключение и добавите его в объявление метода, он позволит другому программисту правильно использовать ваш метод вместе с необходимой обработкой исключений. Для меня это выглядит лучше:

public static int stringToInt(String param) throws NumberFormatException {
        try {
                return Integer.valueOf(param);
        } catch(NumberFormatException e) {
               // return -1;
               throw e;
        }
}

Ответ 4

Java 8 без API:

 Optional.ofNullable(strNum)
         .map(Integer::valueOf).orElse(null);