Java 在预期时处理 NumberFormatException 的正确方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4410107/
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
What is the proper way to handle a NumberFormatException when it is expected?
提问by Erick Robertson
I'm running into this situation where I need to parse a String
into an int
and I don't know what to do with the NumberFormatException
. The compiler doesn't complain when I don't catch it, but I just want to make sure that I'm handling this situation properly.
我遇到了这种情况,我需要将 a 解析String
为 anint
而我不知道如何处理NumberFormatException
. 当我没有抓住它时,编译器不会抱怨,但我只是想确保我正确处理了这种情况。
private int getCurrentPieceAsInt() {
int i = 0;
try {
i = Integer.parseInt(this.getCurrentPiece());
} catch (NumberFormatException e) {
i = 0;
}
return i;
}
I want to just simplify my code like this. The compiler doesn't have a problem with it, but the thread dies on the NumberFormatException
.
我只想像这样简化我的代码。编译器没有问题,但是线程在NumberFormatException
.
private int getCurrentPieceAsInt() {
int i = 0;
i = Integer.parseInt(this.getCurrentPiece());
return i;
}
Google CodePro wants me to log the exception in some way, and I agree that this is best practice.
Google CodePro 希望我以某种方式记录异常,我同意这是最佳实践。
private int getCurrentPieceAsInt() {
int i = 0;
try {
i = Integer.parseInt(this.getCurrentPiece());
} catch (NumberFormatException e) {
i = 0;
e.printStackTrace();
}
return i;
}
I want this method to return 0
when the current piece is not a number or cannot be parsed. When I don't catch the NumberFormatException
explicitly, does it not assign the variable i
? Or is there some default value that Integer.parseInt()
returns?
0
当当前片段不是数字或无法解析时,我希望此方法返回。当我没有NumberFormatException
明确捕获时,它不会分配变量i
吗?或者是否有一些Integer.parseInt()
返回的默认值?
General style says that if I catch an exception, I should log it somewhere. I don't want to log it. It's normal operation for this exception to be thrown sometimes, which also doesn't sit well with me. I cannot find a function, however, which will tell me if Integer.parseInt()
will throw an exception. So my only course of action seems to be to just call it and catch the exception.
一般风格说,如果我捕捉到异常,我应该将它记录在某个地方。我不想记录它。有时抛出这个异常是正常的操作,这也不太适合我。但是,我找不到一个函数,它会告诉我是否Integer.parseInt()
会抛出异常。所以我唯一的行动方案似乎就是调用它并捕获异常。
The javadocfor parseInt
doesn't help much.
该javadoc的为parseInt
没有太大帮助。
Here are the specific questions I'd like to know:
以下是我想知道的具体问题:
- Is there a method that I can call that will tell me if
Integer.parseInt()
will throw aNumberFormatException
before calling it? Then I would have no problem logging this, since it should never happen. - If I simply do not catch the exception, will the valiable not get assigned? Then I will simply initialize it to the value that I want when it's not a number and not catch the exception.
- Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to
AWTEvent.consume()
. If so, then I will do this so that Google CodePro doesn't see this as "unlogged".
- 有没有我可以调用的方法,它会告诉我在调用它之前是否
Integer.parseInt()
会抛出一个NumberFormatException
?那么我记录这个没有问题,因为它永远不会发生。 - 如果我只是不捕获异常,是否不会分配变量?然后,当它不是数字时,我将简单地将其初始化为我想要的值,并且不会捕获异常。
- 有没有办法以某种方式明确标记异常我不关心它?我认为这将类似于
AWTEvent.consume()
. 如果是这样,那么我会这样做,以便 Google CodePro 不会将其视为“未记录”。
采纳答案by Cameron Skinner
- Is there a method that I can call that will tell me if Integer.parseInt() will throw a NumberFormatException before calling it? Then I would have no problem logging this, since it should never happen.
- 有没有我可以调用的方法来告诉我 Integer.parseInt() 在调用它之前是否会抛出 NumberFormatException?那么我记录这个没有问题,因为它永远不会发生。
Sadly, no. At least not in the core Java API. It's easy to write one, however - just modify the code below.
可悲的是没有。至少不是在核心 Java API 中。然而,编写一个很容易——只需修改下面的代码。
- If I simply do not catch the exception, will the valiable not get assigned? Then I will simply initialize it to the value that I want when it's not a number and not catch the exception.
- 如果我只是不捕获异常,是否不会分配变量?然后,当它不是数字时,我将简单地将其初始化为我想要的值,并且不会捕获异常。
If you do not catch the exception then the stack will unwind until it hits a catch block that will handle it, or it will unwind completely and halt the thread. The variable will, in fact, not be assigned but this is not exactly what you want.
如果您没有捕获异常,那么堆栈将展开直到它遇到一个可以处理它的 catch 块,否则它将完全展开并停止线程。事实上,变量不会被赋值,但这并不是你想要的。
- Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".
- 有没有办法以某种方式明确标记异常我不关心它?我认为这类似于 AWTEvent.consume()。如果是这样,那么我会这样做,以便 Google CodePro 不会将其视为“未记录”。
There may be a way to tell CodePro to ignore this particular warning. Certainly with tools like FindBugs and Checkstyle you can turn off warnings in specific locations. (EDIT: @Andy has pointed out how to do this.)
可能有一种方法可以告诉 CodePro 忽略此特定警告。当然,使用 FindBugs 和 Checkstyle 等工具,您可以关闭特定位置的警告。(编辑:@Andy 已经指出了如何做到这一点。)
I suspect what you want is something like the Commons lang package mentioned by @daveb. It's pretty easy to write such a function:
我怀疑你想要的是@daveb提到的Commons lang包。编写这样的函数非常容易:
int parseWithDefault(String s, int def) {
try {
return Integer.parseInt(s);
}
catch (NumberFormatException e) {
// It's OK to ignore "e" here because returning a default value is the documented behaviour on invalid input.
return def;
}
}
回答by Marcus Leon
You should catch the Exception as you are doing. It is annoying, but the best approach.
您应该在执行时捕获异常。这很烦人,但最好的方法。
There is no Java API method that will return 0 when the string is not a valid int.
没有 Java API 方法会在字符串不是有效 int 时返回 0。
When the string is not an int, an exception will be thrown so your int variable will not be set unless you catch the exception as you are doing.
当字符串不是 int 时,将抛出异常,因此除非您在执行时捕获异常,否则不会设置您的 int 变量。
回答by darioo
Your first code block is correct. i
won't be implicitly converted to 0 when an exception occurs and you have to catch that exception. Setting i
to 0 inside catch
is correct; although you can simply replace i = 0;
with return 0;
. You cannot avoid exception handling in this case.
您的第一个代码块是正确的。i
发生异常时不会隐式转换为 0,您必须捕获该异常。i
里面设置为0catch
是正确的;虽然你可以简单地替换i = 0;
为return 0;
. 在这种情况下,您无法避免异常处理。
To clarify, you can use this:
为了澄清,你可以使用这个:
private int getCurrentPieceAsInt() {
int i = 0;
try {
i = Integer.parseInt(this.getCurrentPiece());
} catch (NumberFormatException e) {
// log that an exception occured if it's needed
return 0;
}
return i;
}
回答by daveb
There is NumberUtils.toInt(String, int)in commons langwhich will do exactly what you want.
在commons lang 中有NumberUtils.toInt(String, int),它可以完全满足您的需求。
NumberUtils.toInt("123", 42) ==> 123
NumberUtils.toInt("abc", 42) ==> 42
回答by Bert F
Create your own convenience method for now and future use:
创建您自己的方便方法供现在和将来使用:
public static int parseInt(final /*@Nullable*/ String s, final int valueIfInvalid) {
try {
if (s == null) {
return valueIfInvalid;
} else {
return Integer.parseInt(s);
}
} catch (final NumberFormatException ex) {
return valueIfInvalid;
}
}
Is there a method that I can call that will tell me if Integer.parseInt() will throw a NumberFormatException before calling it? Then I would have no problem logging this, since it should never happen.
有没有我可以调用的方法来告诉我 Integer.parseInt() 在调用它之前是否会抛出 NumberFormatException?那么我记录这个没有问题,因为它永远不会发生。
Not that I'm aware of. Keep in mind that if there were, you likely end up parsing the value twice (once to validate and once to parse it). I understand you want to avoid the exception, but in this case, this is catching the exception is the standard idiom in Java and it doesn't provide another (at least that I know of).
不是我所知道的。请记住,如果存在,您可能最终会解析该值两次(一次验证,一次解析)。我知道您想避免异常,但在这种情况下,这是捕获异常是 Java 中的标准习语,它不提供另一个(至少我知道)。
If I simply do not catch the exception, will the valiable not get assigned? Then I will simply initialize it to the value that I want when it's not a number and not catch the exception.
如果我只是不捕获异常,是否不会分配变量?然后,当它不是数字时,我将简单地将其初始化为我想要的值,并且不会捕获异常。
You must catch the exception (even if it does nothing) or it will escape the block and throw up through the stack.
您必须捕获异常(即使它什么都不做),否则它会逃逸块并通过堆栈抛出。
Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".
有没有办法以某种方式明确标记异常我不关心它?我认为这类似于 AWTEvent.consume()。如果是这样,那么我会这样做,以便 Google CodePro 不会将其视为“未记录”。
I don't know of any. I would use the above convenience method (I have something similar in a small collection of general utilities I have available for use on my all projects).
我一个都不知道。我会使用上面的方便方法(我在一小部分通用实用程序中有类似的东西,我可以在我的所有项目中使用)。
I wouldn't log it if its truly a normal condition that you are handling. I'm not familiiar with Google CodePro, but I would hope there is a way to suppress the warning, e.g. some sort of @SuppressWarnings("xxx") annotation/keyword.
如果它确实是您正在处理的正常情况,我不会记录它。我不熟悉 Google CodePro,但我希望有一种方法可以抑制警告,例如某种 @SuppressWarnings("xxx") 注释/关键字。
Edit:I wanted to point out these comments in the comments below
编辑:我想在下面的评论中指出这些评论
This approach still doesn't handle the exception. It's bad form to catch an exception and do nothing with it. This is why I am looking for a better solution
这种方法仍然不能处理异常。捕获异常而不对其进行任何操作是不好的形式。这就是为什么我正在寻找更好的解决方案
.
.
... The exception (the situation) is being handledby returning the indicated valueIfInvalid. The "bad form"you are referring to the poor practice of blindly and unthinkingly writing empty catch blocksand never going back to truly consider and address the case. If the exception situation is considered and does the right thingfor the situation (even if the right thing is to do nothing), then you've "handled" the exception.
...正在通过返回指示的 valueIfInvalid来处理异常(情况)。您所指的“不良形式”是指盲目和不假思索地编写空的 catch 块并且永远不会真正考虑和解决案例的不良做法。如果考虑到异常情况并且针对该情况做了正确的事情(即使正确的事情是什么都不做),那么您已经“处理”了异常。
回答by Peter Lawrey
If its not clear how you should handle it from the getter, you shouldn't catch it and let the caller deal with it instead. If you know how it should be handled you should just do that. Logging it may not be required or very useful in this case.
如果不清楚你应该如何从 getter 处理它,你不应该抓住它并让调用者处理它。如果您知道应该如何处理它,您就应该这样做。在这种情况下,记录它可能不需要或非常有用。
Logging an exception is more useful if you don't know how to handle the exception and you are leaving it to the person reading the logs.
如果您不知道如何处理异常并将其留给阅读日志的人,则记录异常会更有用。
回答by Andy Thomas
* Is there a way to mark the exception somehow explicitly that I don't care about it? I'm thinking this would be something similar to AWTEvent.consume(). If so, then I will do this so that Google CodePro doesn't see this as "unlogged".
Yes, you can locally disable a CodePro audit rule for one line of code:
是的,您可以在本地禁用一行代码的 CodePro 审核规则:
http://code.google.com/javadevtools/codepro/doc/features/audit/locally_disabling_audit_rules.html
http://code.google.com/javadevtools/codepro/doc/features/audit/locally_disabling_audit_rules.html
That said, it is not necessarily required to include diagnostic logging in every exception catch block. Sometimes, the best action is to take a default course. Sometime it's to interact with the user. It depends.
也就是说,不一定需要在每个异常捕获块中都包含诊断日志记录。有时,最好的行动是采取默认路线。有时是与用户交互。这取决于。
回答by rob
As others have mentioned, there is not a built-in core Java API method you can call to validate an integer, but you can use the Character
class to validate your input withoutusing exception handling. For example:
正如其他人所提到的,没有可以调用的内置核心 Java API 方法来验证整数,但您可以使用Character
该类来验证您的输入,而无需使用异常处理。例如:
package com.example.parseint;
public class ValidateIntExample {
public static boolean isInteger(String s) {
if (s == null) {
return false;
}
s = s.trim();
if (s.length() == 0) {
return false;
}
int start = 0;
if (s.charAt(0) == '-') { // handle negative numbers
if (s.length() == 1) {
return false;
}
else {
start = 1;
}
}
for (int i = start; i < s.length(); i++) {
if (! Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
}
}
In fact, parseInt
itself uses Character.isDigit
internally, which you can verify in the JRE source code. (Sorry, I would have included the parseInt
method here, but I'm not sure if I'm allowed under the license terms.) If you're using Eclipse and you have the JRE source code attached to your project, you can right-click on the method Integer.parseInt
in your code and click Open Declaration.
其实parseInt
本身就是Character.isDigit
内部使用的,可以在JRE源码中验证。(抱歉,我会在parseInt
此处包含该方法,但我不确定许可条款是否允许我这样做。)如果您使用的是 Eclipse 并且您的项目附加了 JRE 源代码,您可以对 -单击Integer.parseInt
代码中的方法,然后单击打开声明。