「入力された文字列がint型に変換されるかどうかをチェックしたい」という場合、次のように判定しているソースコードを見かけることがあります。
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException e) {
return false;
}
まず変換してみてダメならfalseにする、そして例外を握りつぶすなど、この方法には個人的に違和感があり、なんとなく敬遠の対象でした。身もふたもない言い方をすれば、生理的嫌悪感があります。
そういうわけでInteger#parseInt
を利用せずに、与えられた文字列がintに変換できるかどうかチェックするメソッドを作っておきました(´・ω・`)
final public class IntegerUtils {
public static void main(String[] args) {
System.out.println(IntegerUtils.isInteger("123")); //=> true
System.out.println(IntegerUtils.isInteger("-23")); //=> true
System.out.println(IntegerUtils.isInteger("12A")); //=> false
System.out.println(IntegerUtils.isInteger("ABC")); //=> false
// 境界値でも正確に判定できている。
System.out.println(IntegerUtils.isInteger("2147483647")); //=> true
System.out.println(IntegerUtils.isInteger("2147483648")); //=> false
System.out.println(IntegerUtils.isInteger("-2147483648")); //=> true
System.out.println(IntegerUtils.isInteger("-2147483649")); //=> false
// ==== 2017-05-16 テストケースを追加した。 ===
System.out.println(IntegerUtils.isInteger("0")); //=> true
System.out.println(IntegerUtils.isInteger("473")); //=> true
System.out.println(IntegerUtils.isInteger("+42")); //=> true
System.out.println(IntegerUtils.isInteger("-0")); //=> true
System.out.println(IntegerUtils.isInteger("-")); //=> false
System.out.println(IntegerUtils.isInteger("+5")); //=> true
System.out.println(IntegerUtils.isInteger("123")); //=> true
System.out.println(IntegerUtils.isInteger("١٢٣")); //=> true
}
/**
* 文字列が10進数の整数であり、かつintの範疇に収まるかどうかを判定する。
* @param str 判定対象の文字列。
* @return 文字列が10進数の整数であり、かつintの範疇に収まる場合はTrue.
*/
public static final boolean isInteger(String str) {
if (str == null
|| str.isEmpty()
|| str.equals("+")
|| str.equals("-")) {
return false;
}
char first = str.charAt(0);
int i = (first == '+' || first == '-') ? 1 : 0;
int sign = (first == '-') ? -1 : 1;
int len = str.length();
long integer = 0;
while (i < len) {
char ch = str.charAt(i++);
int digit = Character.digit(ch, 10);
if (digit == -1) {
return false;
}
integer = integer * 10 + sign * digit;
if (integer < Integer.MIN_VALUE || Integer.MAX_VALUE < integer) {
return false;
}
}
return true;
}
// ==== 2017-05-16 ロジックに誤りがあったため全面的に修正した。 ===
// /**
// * 文字列が10進数の整数であり、かつintの範疇に収まるかどうかを判定する。
// * @param str 判定対象の文字列。
// * @return 文字列が10進数の整数であり、かつintの範疇に収まる場合はTrue.
// */
// public static final boolean isInteger(String str) {
// if (str == null || str.isEmpty()) {
// return false;
// }
//
// boolean isNegative = str.charAt(0) == '-';
// int i = isNegative ? 1 : 0;
// int sign = isNegative ? -1: 1;
// int len = str.length();
// long integer = 0;
//
// while (i < len) {
// int digit = str.charAt(i++) - '0';
// if (digit < 0 || 9 < digit) {
// return false;
// }
//
// integer = integer * 10 + sign * digit;
// if (integer < Integer.MIN_VALUE || Integer.MAX_VALUE < integer) {
// return false;
// }
// }
// return true;
// }
}
アルゴリズムというか、やっていることはごく単純で、与えられた引数が整数に変換できるかどうかを1文字ずつ検査しているだけ。Integer#parseInt
を利用する方法と違いがあるとすれば、例外を利用していないということぐらいですが、「例外ならfalse」というよりは洗練されていると個人的には感じています。自己満足(´・ω・`)