我经常遇到需要解析数值的情况(例如使用Integer.parseInt或Double.parseDouble)并且我有多个值。问题是,我发现自己必须复制异常处理,它变得丑陋。例如,请使用以下代码:
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...
}
处理这种情况是否有良好的模式?
我不想使用单次尝试捕获,因为我想继续解析剩余的数字。
我应该提一下,在这个例子中,值没有被初始化,而是在实际的程序代码中。只有在字符串值可解析时才会进行赋值。
答案 0 :(得分:4)
只提取一个方法:
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;
Double mediumVal;
Double 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 null;
}
}
答案 1 :(得分:1)
在Double的文档中,您可以解决问题。
为避免在无效字符串上调用此方法并抛出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"
答案 2 :(得分:1)
您可以实现这样的类:
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);
答案 3 :(得分:0)
我只会使用一个try-catch来获取所有值。
答案 4 :(得分:0)
这是一个使用标志和循环来防止再次发生异常的解决方案:
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);
答案 5 :(得分:0)
当您期望解析失败时,我发现根本不使用基于异常的方法更简单。除了导致更简洁的代码之外,它还可以快几个数量级,因为它避免了抛出异常的代价。
不是像我自己的方法那样编写,而是像往常一样拯救番石榴。您可以使用Doubles.tryParse重写解析,如下所示:
Double lowVal, mediumVal, highVal;
String lowString = "1.2", mediumString = "null", highString = "7.9";
lowVal = Doubles.tryParse(lowString);
mediumVal = Doubles.tryParse(mediumString);
highVal = Doubles.tryParse(highString);
非常简洁!请注意,执行此操作后,任何无法解析的值都将为null
。如果解析失败,您实际上并没有说过要分配给双打的值(实际上您的原始示例将不会编译,因为值可能未初始化)。
假设您想将值0.0分配给任何失败的解析 - 您可以使用Objects.firstNonNull()来执行此操作:
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);
答案 6 :(得分: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);