Java 封装 Integer.parseInt() 的好方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1486077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Good way to encapsulate Integer.parseInt()
提问by Bad Horse
I have a project in which we often use Integer.parseInt()
to convert a String to an int. When something goes wrong (for example, the String
is not a number but the letter a
, or whatever) this method will throw an exception. However, if I have to handle exceptions in my code everywhere, this starts to look very ugly very quickly. I would like to put this in a method, however, I have no clue how to return a clean value in order to show that the conversion went wrong.
我有一个项目,我们经常在其中Integer.parseInt()
将 String 转换为 int。当出现问题时(例如,String
不是数字而是字母a
,或其他),此方法将抛出异常。但是,如果我必须在我的代码中处处处理异常,这很快就会变得非常难看。我想把它放在一个方法中,但是,我不知道如何返回一个干净的值来表明转换出错了。
In C++ I could have created a method that accepted a pointer to an int and let the method itself return true or false. However, as far as I know, this is not possible in Java. I could also create an object that contains a true/false variable and the converted value, but this does not seem ideal either. The same thing goes for a global value, and this might give me some trouble with multithreading.
在 C++ 中,我可以创建一个方法,它接受一个指向 int 的指针并让方法本身返回 true 或 false。但是,据我所知,这在 Java 中是不可能的。我也可以创建一个包含真/假变量和转换后的值的对象,但这似乎也不理想。同样的事情也适用于全局值,这可能会给我带来多线程的一些麻烦。
So is there a clean way to do this?
那么有没有一种干净的方法来做到这一点?
采纳答案by Jon Skeet
You could return an Integer
instead of an int
, returning null
on parse failure.
您可以返回 anInteger
而不是 an int
,null
在解析失败时返回。
It's a shame Java doesn't provide a way of doing this without there being an exception thrown internally though - you can hide the exception (by catching it and returning null), but it could still be a performance issue if you're parsing hundreds of thousands of bits of user-provided data.
遗憾的是,Java 没有提供一种在内部不抛出异常的情况下执行此操作的方法 - 您可以隐藏异常(通过捕获它并返回 null),但是如果您解析数百个,它仍然可能是一个性能问题数千位用户提供的数据。
EDIT: Code for such a method:
编辑:这种方法的代码:
public static Integer tryParse(String text) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
return null;
}
}
Note that I'm not sure off the top of my head what this will do if text
is null. You should consider that - if it represents a bug (i.e. your code may well pass an invalid value, but should never pass null) then throwing an exception is appropriate; if it doesn't represent a bug then you should probably just return null as you would for any other invalid value.
请注意,如果text
为空,我不确定这会做什么。你应该考虑——如果它代表一个错误(即你的代码很可能传递一个无效值,但不应该传递空值),那么抛出异常是合适的;如果它不代表错误,那么您可能应该像返回任何其他无效值一样返回 null。
Originally this answer used the new Integer(String)
constructor; it now uses Integer.parseInt
and a boxing operation; in this way small values will end up being boxed to cached Integer
objects, making it more efficient in those situations.
最初这个答案使用了new Integer(String)
构造函数;它现在使用Integer.parseInt
和一个拳击操作;通过这种方式,小值最终会被装箱到缓存Integer
对象中,使其在这些情况下更高效。
回答by Adam Maras
My Java is a little rusty, but let me see if I can point you in the right direction:
我的 Java 有点生疏,但让我看看我是否可以为您指明正确的方向:
public class Converter {
public static Integer parseInt(String str) {
Integer n = null;
try {
n = new Integer(Integer.tryParse(str));
} catch (NumberFormatException ex) {
// leave n null, the string is invalid
}
return n;
}
}
If your return value is null
, you have a bad value. Otherwise, you have a valid Integer
.
如果您的返回值为null
,则您的值不正确。否则,您有一个有效的Integer
.
回答by yawn
You can use a Null-Object like so:
您可以像这样使用空对象:
public class Convert {
@SuppressWarnings({"UnnecessaryBoxing"})
public static final Integer NULL = new Integer(0);
public static Integer convert(String integer) {
try {
return Integer.valueOf(integer);
} catch (NumberFormatException e) {
return NULL;
}
}
public static void main(String[] args) {
Integer a = convert("123");
System.out.println("a.equals(123) = " + a.equals(123));
System.out.println("a == NULL " + (a == NULL));
Integer b = convert("onetwothree");
System.out.println("b.equals(123) = " + b.equals(123));
System.out.println("b == NULL " + (b == NULL));
Integer c = convert("0");
System.out.println("equals(0) = " + c.equals(0));
System.out.println("c == NULL " + (c == NULL));
}
}
The result of mainin this example is:
本例中main的结果是:
a.equals(123) = true
a == NULL false
b.equals(123) = false
b == NULL true
c.equals(0) = true
c == NULL false
This way you can always test for failed conversion but still work with the results as Integer instances. You might also want to tweak the number NULLrepresents (≠ 0).
通过这种方式,您始终可以测试失败的转换,但仍然可以将结果作为 Integer 实例处理。您可能还想调整NULL代表的数字(≠ 0)。
回答by Nikolay Ivanov
May be you can use something like this:
也许你可以使用这样的东西:
public class Test {
public interface Option<T> {
T get();
T getOrElse(T def);
boolean hasValue();
}
final static class Some<T> implements Option<T> {
private final T value;
public Some(T value) {
this.value = value;
}
@Override
public T get() {
return value;
}
@Override
public T getOrElse(T def) {
return value;
}
@Override
public boolean hasValue() {
return true;
}
}
final static class None<T> implements Option<T> {
@Override
public T get() {
throw new UnsupportedOperationException();
}
@Override
public T getOrElse(T def) {
return def;
}
@Override
public boolean hasValue() {
return false;
}
}
public static Option<Integer> parseInt(String s) {
Option<Integer> result = new None<Integer>();
try {
Integer value = Integer.parseInt(s);
result = new Some<Integer>(value);
} catch (NumberFormatException e) {
}
return result;
}
}
回答by Nikolay Ivanov
You could also replicate the C++ behaviour that you want very simply
您还可以非常简单地复制您想要的 C++ 行为
public static boolean parseInt(String str, int[] byRef) {
if(byRef==null) return false;
try {
byRef[0] = Integer.parseInt(prop);
return true;
} catch (NumberFormatException ex) {
return false;
}
}
You would use the method like so:
你会像这样使用这个方法:
int[] byRef = new int[1];
boolean result = parseInt("123",byRef);
After that the variable result
it's true if everything went allright and byRef[0]
contains the parsed value.
之后,result
如果一切顺利并byRef[0]
包含解析的值,则变量为真。
Personally, I would stick to catching the exception.
就个人而言,我会坚持捕捉异常。
回答by Andreas Dolk
After reading the answers to the question I think encapsulating or wrapping the parseInt method is not necessary, maybe even not a good idea.
在阅读了问题的答案后,我认为封装或包装 parseInt 方法是没有必要的,甚至可能不是一个好主意。
You could return 'null' as Jon suggested, but that's more or less replacing a try/catch construct by a null-check. There's just a slight difference on the behaviour if you 'forget' error handling: if you don't catch the exception, there's no assignment and the left hand side variable keeps it old value. If you don't test for null, you'll probably get hit by the JVM (NPE).
您可以按照 Jon 的建议返回 'null',但这或多或少地用空检查替换了 try/catch 构造。如果您“忘记”错误处理,则行为会略有不同:如果您没有捕获异常,则没有赋值,左侧变量将保持旧值。如果您不测试 null,您可能会受到 JVM (NPE) 的影响。
yawn's suggestion looks more elegant to me, because I do not like returning null to signal some errors or exceptional states. Now you have to check referential equality with a predefined object, that indicates a problem. But, as others argue, if again you 'forget' to check and a String is unparsable, the program continous with the wrapped int inside your 'ERROR' or 'NULL' object.
哈欠的建议对我来说看起来更优雅,因为我不喜欢返回 null 来表示某些错误或异常状态。现在您必须使用预定义的对象检查引用相等性,这表明存在问题。但是,正如其他人争论的那样,如果您再次“忘记”检查并且字符串无法解析,则程序将继续使用“ERROR”或“NULL”对象内的包装 int。
Nikolay's solution is even more object orientated and will work with parseXXX methods from other wrapper classes aswell. But in the end, he just replaced the NumberFormatException by an OperationNotSupported exception - again you need a try/catch to handle unparsable inputs.
Nikolay 的解决方案更加面向对象,并且也适用于来自其他包装类的 parseXXX 方法。但最后,他只是将 NumberFormatException 替换为 OperationNotSupported 异常 - 您再次需要 try/catch 来处理无法解析的输入。
So, its my conclusion to not encapsulate the plain parseInt method. I'd only encapsulate if I could add some (application depended) error handling as well.
所以,我的结论是不封装普通的 parseInt 方法。如果我也可以添加一些(依赖于应用程序)错误处理,我只会封装。
回答by Joachim Sauer
What behaviour do you expect when it's not a number?
当它不是数字时,您期望什么行为?
If, for example, you often have a default value to use when the input is not a number, then a method such as this could be useful:
例如,如果您经常在输入不是数字时使用默认值,那么这样的方法可能很有用:
public static int parseWithDefault(String number, int defaultVal) {
try {
return Integer.parseInt(number);
} catch (NumberFormatException e) {
return defaultVal;
}
}
Similar methods can be written for different default behaviour when the input can't be parsed.
当无法解析输入时,可以为不同的默认行为编写类似的方法。
回答by Thorbj?rn Ravn Andersen
I would suggest you consider a method like
我建议你考虑一种方法
IntegerUtilities.isValidInteger(String s)
which you then implement as you see fit. If you want the result carried back - perhaps because you use Integer.parseInt() anyway - you can use the array trick.
然后你可以按照你认为合适的方式实施。如果您想要返回结果 - 也许是因为您无论如何都使用 Integer.parseInt() - 您可以使用数组技巧。
IntegerUtilities.isValidInteger(String s, int[] result)
where you set result[0] to the integer value found in the process.
您将 result[0] 设置为在过程中找到的整数值。
回答by Carl
This is somewhat similar to Nikolay's solution:
这有点类似于 Nikolay 的解决方案:
private static class Box<T> {
T me;
public Box() {}
public T get() { return me; }
public void set(T fromParse) { me = fromParse; }
}
private interface Parser<T> {
public void setExclusion(String regex);
public boolean isExcluded(String s);
public T parse(String s);
}
public static <T> boolean parser(Box<T> ref, Parser<T> p, String toParse) {
if (!p.isExcluded(toParse)) {
ref.set(p.parse(toParse));
return true;
} else return false;
}
public static void main(String args[]) {
Box<Integer> a = new Box<Integer>();
Parser<Integer> intParser = new Parser<Integer>() {
String myExclusion;
public void setExclusion(String regex) {
myExclusion = regex;
}
public boolean isExcluded(String s) {
return s.matches(myExclusion);
}
public Integer parse(String s) {
return new Integer(s);
}
};
intParser.setExclusion("\D+");
if (parser(a,intParser,"123")) System.out.println(a.get());
if (!parser(a,intParser,"abc")) System.out.println("didn't parse "+a.get());
}
The main method demos the code. Another way to implement the Parser interface would obviously be to just set "\D+" from construction, and have the methods do nothing.
main 方法演示了代码。实现 Parser 接口的另一种方法显然是从构造中设置“\D+”,并且让这些方法什么都不做。
回答by James Bassett
You couldroll your own, but it's just as easy to use commons lang's StringUtils.isNumeric()
method. It uses Character.isDigit()to iterate over each character in the String.
您可以推出自己的方法,但使用 commons lang 的StringUtils.isNumeric()
方法同样容易。它使用Character.isDigit()迭代字符串中的每个字符。