Java 如何使用相同的catch块处理解析数字?
我经常遇到这样一种情况:我需要解析一个数值(例如使用Integer.parseInt或Double.parseDouble),并且我有多个值。问题是,我发现自己必须复制异常处理,它变得丑陋。例如,以以下代码为例:Java 如何使用相同的catch块处理解析数字?,java,exception-handling,numberformatexception,Java,Exception Handling,Numberformatexception,我经常遇到这样一种情况:我需要解析一个数值(例如使用Integer.parseInt或Double.parseDouble),并且我有多个值。问题是,我发现自己必须复制异常处理,它变得丑陋。例如,以以下代码为例: double lowVal, mediumVal, highVal; String lowString = "1.2", mediumString = "null", highString = "7.9"; try { lowVal = parseDouble(lowStri
double lowVal, mediumVal, highVal;
String lowString = "1.2", mediumString = "null", highString = "7.9";
try {
lowVal = parseDouble(lowString);
} catch (NumberFormatException NaN) {
//Don't care, just carry on trying to parse the rest...
}
try {
mediumVal = parseDouble(mediumString);
} catch (NumberFormatException NaN) {
//Don't care, just carry on trying to parse the rest...
}
try {
highVal = parseDouble(highString);
} catch (NumberFormatException NaN) {
//Don't care, just carry on trying to parse the rest...
}
处理这种情况有好的模式吗
我不想使用一个try-catch,因为我想继续解析其余的数字
我应该提到的是,在这个例子中,这些值并没有初始化,但在实际的程序代码中它们会被初始化。只有当字符串值是可解析的时,才会发生赋值。我只会对所有值使用一个try-catch 只需提取一个方法:
double lowVal, mediumVal, highVal;
String lowString = "1.2", mediumString = "null", highString = "7.9";
lowVal = parseDouble(lowString);
mediumVal = parseDouble(mediumString);
highVal = parseDouble(highString);
double parseDouble(String s) {
try {
return Double.parseDouble(s);
} catch (NumberFormatException e) {
return Double.NAN;
}
}
或
下面是一个使用标志和循环防止异常再次发生的解决方案:
double lowVal, mediumVal, highVal;
String lowString = "1.2", mediumString = "null", highString = "7.9";
int count = 0;
boolean lowFlag = false, medFlag = false, highFlag = false;
do{
try {
count = 0;
count++;
if(!lowFlag)
lowVal = parseDouble(lowString);
count++;
if(!medFlag)
mediumVal = parseDouble(mediumString);
count++;
if(!highFlag)
highVal = parseDouble(highString);
break;
} catch (NumberFormatException NaN) {
if(count==0)
lowFlag = true;
else if(count==1)
medFlag = true;
else if(count==2)
highFlag = true;
}
}while(true);
在你的文档中有你问题的解决方案
为了避免对无效字符串调用此方法并引发NumberFormatException,可以使用下面的正则表达式来筛选输入字符串
用parseDouble方法包装所有内容,并按照说明进行操作
if (Pattern.matches(fpRegex, myString))
Double.valueOf(myString); // Will not throw NumberFormatException
else {
// Perform suitable alternative action
}
从你的问题来看,这似乎被另一条评论所取代
//Don't care, just carry on trying to parse the rest...
如果链接处于活动状态(不应该发生),则这是正则表达式
final String Digits = "(\\p{Digit}+)";
final String HexDigits = "(\\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
final String Exp = "[eE][+-]?"+Digits;
final String fpRegex =
("[\\x00-\\x20]*"+ // Optional leading "whitespace"
"[+-]?(" + // Optional sign character
"NaN|" + // "NaN" string
"Infinity|" + // "Infinity" string
// A decimal floating-point string representing a finite positive
// number without a leading sign has at most five basic pieces:
// Digits . Digits ExponentPart FloatTypeSuffix
//
// Since this method allows integer-only strings as input
// in addition to strings of floating-point literals, the
// two sub-patterns below are simplifications of the grammar
// productions from the Java Language Specification, 2nd
// edition, section 3.10.2.
// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
// . Digits ExponentPart_opt FloatTypeSuffix_opt
"(\\.("+Digits+")("+Exp+")?)|"+
// Hexadecimal strings
"((" +
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "(\\.)?)|" +
// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
")[pP][+-]?" + Digits + "))" +
"[fFdD]?))" +
"[\\x00-\\x20]*");// Optional trailing "whitespace"
您可以实现如下类:
class DoubleParser {
private Optional<Double> parsedOptional;
private DoubleParser(Optional<Double> parsedOptional) {
this.parsedOptional = parsedOptional;
}
public static DoubleParser parse(final String s) {
Double parsed = null;
try {
parsed = Double.valueOf(s);
} catch ( NumberFormatException e ) {
parsed = null;
}
return new DoubleParser(Optional.ofNullable(parsed));
}
public double get() {
return get(0.0);
}
public double get(final double defaultValue) {
return parsedOptional.orElse(defaultValue);
}
}
double lowVal, mediumVal, highVal;
String lowString = "1.2", mediumString = "null", highString = "7.9";
lowVal = DoubleParser.parse(lowString).get();
mediumVal = DoubleParser.parse(mediumString).get();
highVal = DoubleParser.parse(highString).get();
// with default value if you want
mediumVal = DoubleParser.parse(mediumString).get(Double.NaN);
当您期望解析失败时,我发现根本不使用基于异常的方法更简单。除了生成更简洁的代码外,它还可以快几个数量级,因为它避免了抛出异常的开销 与其写我自己的方法,不如像往常一样用番石榴来解救。您可以使用类似的方法重写解析: 非常简洁!请注意,执行此操作后,任何无法解析的值都将
null
。如果解析失败,您实际上还没有说要为double分配什么值(事实上,您的原始示例不会编译,因为这些值可能未初始化)
假设您希望将值0.0分配给任何失败的解析-您可以使用:
Double lowVal, mediumVal, highVal;
String lowString = "1.2", mediumString = "null", highString = "7.9";
lowVal = Objects.firstNonNull(Doubles.tryParse(lowString), 0.0);
mediumVal = Objects.firstNonNull(Doubles.tryParse(mediumString), 0.0);
highVal = Objects.firstNonNull(Doubles.tryParse(highString), 0.0);
我决定使用这种方法:
public static double parseWithDefault(String value, double fallback) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException NaN) {
return fallback;
}
}
然后可以这样做作业:
lowVal = parseWithDefault(lowString, lowVal);
mediumVal = parseWithDefault(mediumString, mediumVal);
highVal = parseWithDefault(highString, highVal);
只需对所有三个使用一个try-catch,但我希望其余的继续执行。如果您试图在同一个try块中解析所有这些异常,那么每当抛出异常时,您如何继续解析其余的异常?也许可以将单个try捕获放在一个带有标志的循环中,以防止再次执行最后一个抛出的异常。我明白了。你不能继续解析;这就是RuntimeExceptions的问题所在,您要么暂停,要么捕获每一个异常。如果解析失败,您没有提到要分配给
lowVal
和朋友的内容。你不能只是“不在乎”,因为上面的代码甚至不会编译。它会抱怨lowVal可能未初始化:因为如果parseDouble失败,它将在分配任何值之前抛出,然后捕获异常,在作用域中保留一个未初始化的lowVal
。但如果该值无效,我不想赋值。@SinaMadanidouble
原语默认值为0.0
,因此它无论如何都会有一个值。该值可能已经在代码中的其他地方赋值了,我只是将其用作一个简单的示例。我想我可以传入当前值并将其用作返回值。在哪里可以找到“fpRegex”?单击名为Double的链接。它有你需要的全部代码,正则表达式相当难看,所以我想我更喜欢其他方法。不过,这是一个不错的选择。你把它藏在一个方法中,就再也不必看到它丑陋的一面了:)那么为什么不使用try-catch呢?:)很好的解决方案,但不幸的是,我不能在Android中使用它,因为它不支持Java 8。@SinaMadani我的错,我自己不能在Android上等待Java 8。问题是冗长。我不介意有空的catch块,但我希望有一个解决方案可以减少代码,而不是增加代码。
public static double parseWithDefault(String value, double fallback) {
try {
return Double.parseDouble(value);
} catch (NumberFormatException NaN) {
return fallback;
}
}
lowVal = parseWithDefault(lowString, lowVal);
mediumVal = parseWithDefault(mediumString, mediumVal);
highVal = parseWithDefault(highString, highVal);