java中的String to Int - 可能是坏数据,需要避免异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/174502/
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
String to Int in java - Likely bad data, need to avoid exceptions
提问by Chris Cudmore
Seeing as Java doesn't have nullable types, nor does it have a TryParse(), how do you handle input validation without throwing an exceptions?
鉴于 Java 没有可为空类型,也没有 TryParse(),您如何处理输入验证而不抛出异常?
The usual way:
通常的方式:
String userdata = /*value from gui*/
int val;
try
{
val = Integer.parseInt(userdata);
}
catch (NumberFormatException nfe)
{
// bad data - set to sentinel
val = Integer.MIN_VALUE;
}
I could use a regex to check if it's parseable, but that seems like a lot of overhead as well.
我可以使用正则表达式来检查它是否可解析,但这似乎也有很多开销。
What's the best practice for handling this situation?
处理这种情况的最佳做法是什么?
EDIT: Rationale: There's been a lot of talk on SO about exception handling, and the general attitude is that exceptions should be used for unexpected scenarios only. However, I think bad user input is EXPECTED, not rare. Yes, it really is an academic point.
编辑:基本原理:关于异常处理的 SO 有很多讨论,一般的态度是异常应该只用于意外情况。然而,我认为糟糕的用户输入是预期的,并不罕见。是的,这确实是一个学术观点。
Further Edits:
进一步编辑:
Some of the answers demonstrate exactly what is wrong with SO. You ignore the question being asked, and answer another question that has nothing to do with it. The question isn't asking about transition between layers. The question isn't asking what to return if the number is un-parseable. For all you know, val = Integer.MIN_VALUE; is exactly the right option for the application that this completely context free code snippet was take from.
一些答案确切地说明了 SO 有什么问题。你忽略了被问到的问题,并回答了另一个与它无关的问题。问题不是询问层之间的过渡。问题不是问如果数字不可解析,返回什么。众所周知,val = Integer.MIN_VALUE; 对于这个完全上下文无关的代码片段所取自的应用程序来说,这正是正确的选择。
采纳答案by Steve B.
That's pretty much it, although returning MIN_VALUE is kind of questionable, unless you're sure it's the right thing to use for what you're essentially using as an error code. At the very least I'd document the error code behavior, though.
差不多就是这样,尽管返回 MIN_VALUE 有点可疑,除非您确定将其用于您本质上用作错误代码的内容是正确的。不过,至少我会记录错误代码的行为。
Might also be useful (depending on the application) to log the bad input so you can trace.
记录错误输入也可能很有用(取决于应用程序),以便您可以进行跟踪。
回答by arinte
Put some if statements in front of it. if (null != userdata )
在它前面放一些 if 语句。如果(空!= 用户数据)
回答by Shimi Bandiel
I think the best practice is the code you show.
我认为最佳实践是您展示的代码。
I wouldn't go for the regex alternative because of the overhead.
由于开销,我不会选择正则表达式。
回答by asterite
What's the problem with your approach? I don't think doing it that way will hurt your application's performance at all. That's the correct way to do it. Don't optimize prematurely.
你的方法有什么问题?我认为这样做根本不会损害应用程序的性能。这是正确的做法。不要过早优化。
回答by Grant Wagner
I'm sure it is bad form, but I have a set of static methods on a Utilities class that do things like Utilities.tryParseInt(String value)
which returns 0 if the String is unparseable and Utilities.tryParseInt(String value, int defaultValue)
which allows you to specify a value to use if parseInt()
throws an exception.
我确定这是错误的形式,但是我在 Utilities 类上有一组静态方法,它们执行诸如Utilities.tryParseInt(String value)
如果字符串不可解析则返回 0 以及Utilities.tryParseInt(String value, int defaultValue)
允许您指定一个值以在parseInt()
引发异常时使用的值。
I believe there are times when returning a known value on bad input is perfectly acceptable. A very contrived example: you ask the user for a date in the format YYYYMMDD and they give you bad input. It may be perfectly acceptable to do something like Utilities.tryParseInt(date, 19000101)
or Utilities.tryParseInt(date, 29991231);
depending on the program requirements.
我相信有时在错误输入上返回已知值是完全可以接受的。一个非常人为的例子:你要求用户输入 YYYYMMDD 格式的日期,他们给你错误的输入。执行类似Utilities.tryParseInt(date, 19000101)
或Utilities.tryParseInt(date, 29991231);
取决于程序要求的操作可能是完全可以接受的。
回答by Milhous
You could use a Integer, which can be set to null if you have a bad value. If you are using java 1.6, it will provide auto boxing/unboxing for you.
您可以使用整数,如果您的值不正确,则可以将其设置为 null。如果您使用的是 java 1.6,它将为您提供自动装箱/拆箱。
回答by mjlee
The above code is bad because it is equivalent as the following.
上面的代码很糟糕,因为它等效于以下内容。
// this is bad
int val = Integer.MIN_VALUE;
try
{
val = Integer.parseInt(userdata);
}
catch (NumberFormatException ignoreException) { }
The exception is ignored completely. Also, the magic token is bad because an user can pass in -2147483648 (Integer.MIN_VALUE).
异常被完全忽略。此外,魔术令牌很糟糕,因为用户可以传入 -2147483648 (Integer.MIN_VALUE)。
The generic parse-able question is not beneficial. Rather, it should be relevant to the context. Your application has a specific requirement. You can define your method as
通用的可解析问题没有好处。相反,它应该与上下文相关。您的应用程序有特定要求。您可以将方法定义为
private boolean isUserValueAcceptable(String userData)
{
return ( isNumber(userData)
&& isInteger(userData)
&& isBetween(userData, Integer.MIN_VALUE, Integer.MAX_VALUE )
);
}
Where you can documentation the requirement and you can create well defined and testable rules.
您可以在哪里记录需求,并且可以创建定义明确且可测试的规则。
回答by Tom Hawtin - tackline
For user supplied data, Integer.parseInt is usually the wrong method because it doesn't support internationisation. The java.text
package is your (verbose) friend.
对于用户提供的数据,Integer.parseInt 通常是错误的方法,因为它不支持国际化。该java.text
软件包是您的(详细)朋友。
try {
NumberFormat format = NumberFormat.getIntegerInstance(locale);
format.setParseIntegerOnly(true);
format.setMaximumIntegerDigits(9);
ParsePosition pos = new ParsePosition(0);
int val = format.parse(str, pos).intValue();
if (pos.getIndex() != str.length()) {
// ... handle case of extraneous characters after digits ...
}
// ... use val ...
} catch (java.text.ParseFormatException exc) {
// ... handle this case appropriately ...
}
回答by noah
Here's how I do it:
这是我的方法:
public Integer parseInt(String data) {
Integer val = null;
try {
val = Integer.parseInt(userdata);
} catch (NumberFormatException nfe) { }
return val;
}
Then the null signals invalid data. If you want a default value, you could change it to:
然后空值表示无效数据。如果你想要一个默认值,你可以将其更改为:
public Integer parseInt(String data,int default) {
Integer val = default;
try {
val = Integer.parseInt(userdata);
} catch (NumberFormatException nfe) { }
return val;
}
回答by Bill K
If you can avoid exceptions by testing beforehand like you said (isParsable()) it might be better--but not all libraries were designed with that in mind.
如果您可以像您说的那样通过事先测试来避免异常 (isParsable()),那可能会更好——但并非所有库的设计都考虑到了这一点。
I used your trick and it sucks because stack traces on my embedded system are printed regardless of if you catch them or not :(
我使用了你的技巧,它很糟糕,因为我的嵌入式系统上的堆栈跟踪被打印出来,无论你是否发现它们:(