如何处理具有相同 catch 块的解析数字?
How to handle parsing numbers with same catch block?
我经常遇到需要解析数值(例如使用 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...
}
有没有好的模式来处理这种情况?
我不想使用单次捕获,因为我想继续解析其余数字。
我应该提一下,在这个例子中,值没有被初始化,但在实际的程序代码中它们会被初始化。仅当字符串值可解析时才应进行赋值。
我只想对您的所有值使用一个 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;
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;
}
}
这是一个使用标志和循环来防止异常再次发生的解决方案:
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);
在 Double 的文档中,您可以找到问题的解决方案。
To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the regular expression below can be used to screen the input string
将所有内容包装在 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...
如果 link 变为无效(永远不会发生),这就是正则表达式
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:
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);
当您预期解析失败时,我发现根本不使用基于异常的方法更简单。除了导致更简洁的代码之外,它还可以快几个数量级,因为它避免了抛出异常的代价。
与其编写我自己的方法,不如像往常一样使用 Guava 进行救援。您可以像这样用 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
。如果解析失败,您实际上还没有说出要分配给 Doubles 的值(实际上您的原始示例将无法编译,因为这些值可能未初始化)。
假设您想要将值 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);
我决定使用这个方法:
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);
我经常遇到需要解析数值(例如使用 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...
}
有没有好的模式来处理这种情况?
我不想使用单次捕获,因为我想继续解析其余数字。
我应该提一下,在这个例子中,值没有被初始化,但在实际的程序代码中它们会被初始化。仅当字符串值可解析时才应进行赋值。
我只想对您的所有值使用一个 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;
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;
}
}
这是一个使用标志和循环来防止异常再次发生的解决方案:
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);
在 Double 的文档中,您可以找到问题的解决方案。
To avoid calling this method on an invalid string and having a NumberFormatException be thrown, the regular expression below can be used to screen the input string
将所有内容包装在 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...
如果 link 变为无效(永远不会发生),这就是正则表达式
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:
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);
当您预期解析失败时,我发现根本不使用基于异常的方法更简单。除了导致更简洁的代码之外,它还可以快几个数量级,因为它避免了抛出异常的代价。
与其编写我自己的方法,不如像往常一样使用 Guava 进行救援。您可以像这样用 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
。如果解析失败,您实际上还没有说出要分配给 Doubles 的值(实际上您的原始示例将无法编译,因为这些值可能未初始化)。
假设您想要将值 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);
我决定使用这个方法:
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);