在我的日常Web应用程序开发中,有许多情况我们需要从用户那里获取一些数字输入。
然后将此数字输入传递给应用程序的服务或DAO层。
在某个阶段,因为它是一个数字(整数或浮点数),我们需要将它转换为Integer,如下面的代码片段所示。
String cost = request.getParameter("cost");
if (cost !=null && !"".equals(cost) ){
Integer intCost = Integer.parseInt(cost);
List<Book> books = bookService . findBooksCheaperThan(intCost);
}
在上面的情况中,我必须检查输入是否为空或是否没有输入(空白),或者有时可能存在非数字输入,例如等等,等等。
处理此类情况的最佳方法是什么?
答案 0 :(得分:27)
抓住你的异常并进行适当的异常处理:
if (cost !=null && !"".equals(cost) ){
try {
Integer intCost = Integer.parseInt(cost);
List<Book> books = bookService . findBooksCheaperThan(intCost);
} catch (NumberFormatException e) {
System.out.println("This is not a number");
System.out.println(e.getMessage());
}
}
答案 1 :(得分:4)
答案 2 :(得分:2)
Java的最新版本中的异常并不足以使其避免变得非常重要。使用人们建议的try / catch块;如果你在这个过程的早期就捕获了异常(即,在用户输入之后),那么你将不会在此过程中遇到问题(因为无论如何它都是正确的类型)。
过去的例外情况比现在贵很多;在知道异常实际导致问题之前不要优化性能(在这里它们不会。)
答案 3 :(得分:1)
一个可能性:捕获异常并在用户前端中显示错误消息。
编辑:在gui中的字段中添加一个监听器,并检查那里的用户输入,使用这个解决方案的例外情况应该非常罕见......
答案 4 :(得分:1)
我建议做两件事:
答案 5 :(得分:1)
Apache Commons Lang(from here)方法的文档:
来自java.org.apache.commons.lang3.math.NumberUtils的检查String是否为有效的Java编号。
有效数字包括标有0x限定符的十六进制,科学记数法和用类型限定符标记的数字(例如123L)。
Null
并且空字符串将返回false
。<强>参数:强>
`str` - the `String` to check
<强>返回:强>
`true` if the string is a correctly formatted number
isNumber
:
public static boolean isNumber(final String str) {
if (StringUtils.isEmpty(str)) {
return false;
}
final char[] chars = str.toCharArray();
int sz = chars.length;
boolean hasExp = false;
boolean hasDecPoint = false;
boolean allowSigns = false;
boolean foundDigit = false;
// deal with any possible sign up front
final int start = (chars[0] == '-') ? 1 : 0;
if (sz > start + 1 && chars[start] == '0' && chars[start + 1] == 'x') {
int i = start + 2;
if (i == sz) {
return false; // str == "0x"
}
// checking hex (it can't be anything else)
for (; i < chars.length; i++) {
if ((chars[i] < '0' || chars[i] > '9')
&& (chars[i] < 'a' || chars[i] > 'f')
&& (chars[i] < 'A' || chars[i] > 'F')) {
return false;
}
}
return true;
}
sz--; // don't want to loop to the last char, check it afterwords
// for type qualifiers
int i = start;
// loop to the next to last char or to the last char if we need another digit to
// make a valid number (e.g. chars[0..5] = "1234E")
while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
if (chars[i] >= '0' && chars[i] <= '9') {
foundDigit = true;
allowSigns = false;
} else if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
hasDecPoint = true;
} else if (chars[i] == 'e' || chars[i] == 'E') {
// we've already taken care of hex.
if (hasExp) {
// two E's
return false;
}
if (!foundDigit) {
return false;
}
hasExp = true;
allowSigns = true;
} else if (chars[i] == '+' || chars[i] == '-') {
if (!allowSigns) {
return false;
}
allowSigns = false;
foundDigit = false; // we need a digit after the E
} else {
return false;
}
i++;
}
if (i < chars.length) {
if (chars[i] >= '0' && chars[i] <= '9') {
// no type qualifier, OK
return true;
}
if (chars[i] == 'e' || chars[i] == 'E') {
// can't have an E at the last byte
return false;
}
if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
// single trailing decimal point after non-exponent is ok
return foundDigit;
}
if (!allowSigns
&& (chars[i] == 'd'
|| chars[i] == 'D'
|| chars[i] == 'f'
|| chars[i] == 'F')) {
return foundDigit;
}
if (chars[i] == 'l'
|| chars[i] == 'L') {
// not allowing L with an exponent or decimal point
return foundDigit && !hasExp && !hasDecPoint;
}
// last character is illegal
return false;
}
// allowSigns is true iff the val ends in 'E'
// found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
return !allowSigns && foundDigit;
}
[代码在Apache许可证的第2版下]
答案 6 :(得分:1)
public class Main {
public static void main(String[] args) {
String number;
while(true){
try{
number = JOptionPane.showInputDialog(null);
if( Main.isNumber(number) )
break;
}catch(NumberFormatException e){
System.out.println(e.getMessage());
}
}
System.out.println("Your number is " + number);
}
public static boolean isNumber(Object o){
boolean isNumber = true;
for( byte b : o.toString().getBytes() ){
char c = (char)b;
if(!Character.isDigit(c))
isNumber = false;
}
return isNumber;
}
}
答案 7 :(得分:0)
确定字符串是Int还是Float并以更长的格式表示。
<强>整数强>
String cost=Long.MAX_VALUE+"";
if (isNumeric (cost)) // returns false for non numeric
{
BigInteger bi = new BigInteger(cost);
}
public static boolean isNumeric(String str)
{
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
答案 8 :(得分:0)
使用Scanner类可以避免令人不快的try / catch或regex:
String input = "123";
Scanner sc = new Scanner(input);
if (sc.hasNextInt())
System.out.println("an int: " + sc.nextInt());
else {
//handle the bad input
}
答案 9 :(得分:0)
尝试将奖品转换为十进制格式......
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Bigdecimal {
public static boolean isEmpty (String st) {
return st == null || st.length() < 1;
}
public static BigDecimal bigDecimalFormat(String Preis){
//MathContext mi = new MathContext(2);
BigDecimal bd = new BigDecimal(0.00);
bd = new BigDecimal(Preis);
return bd.setScale(2, RoundingMode.HALF_UP);
}
public static void main(String[] args) {
String cost = "12.12";
if (!isEmpty(cost) ){
try {
BigDecimal intCost = bigDecimalFormat(cost);
System.out.println(intCost);
List<Book> books = bookService.findBooksCheaperThan(intCost);
} catch (NumberFormatException e) {
System.out.println("This is not a number");
System.out.println(e.getMessage());
}
}
}
}
答案 10 :(得分:-1)
我不知道有关以下内容的运行时缺点,但您可以在字符串上运行regexp匹配,以确保它在尝试解析之前是一个数字,因此
cost.matches("-?\\d+\\.?\\d+")
表示浮动
和
cost.matches("-?\\d+")
表示整数
修改强>
请注意@Voo关于max int的评论
答案 11 :(得分:-1)
在Java中,遗憾的是你无法避免使用parseInt函数并且只是捕获异常。那么理论上你可以编写自己的解析器来检查它是否是一个数字,但是你根本就不需要parseInt了。
正则表达式方法存在问题,因为没有什么能阻止某人包含数字&gt; INTEGER.MAX_VALUE将通过正则表达式测试但仍然失败。
答案 12 :(得分:-1)
这取决于您的环境。例如,JSF将负担手动检查和转换字符串&lt; - &gt;的负担。来自您的数字,Bean验证是另一种选择。
您可以在您提供的代码段中立即做什么:
getAsInt(String param)
,其中包含:String.isEmpty()
(自Java 6起),try / catch
如果您碰巧写了很多像这样的代码,那么肯定会想到:
public void myBusinessMethod(@ValidNumber String numberInput) {
// ...
}
(这将是基于拦截器的。)
最后但并非最不重要:保存工作并尝试切换到支持这些常见任务的框架......