标识解析错误的默认值(字符串->双精度/任何数字)

时间:2019-05-10 09:20:25

标签: java string double text-parsing

在Java中使用“默认值”而不是异常检查无效解析结果的最佳实践是什么?

我正在处理的(旧的)项目具有故障安全的util-method,可将String解析为double,例如:

//null checks, LOG output etc removed for readability
double parseDouble(String input, double defaultValue){ 
  try{    
    return Double.parseDouble(input)
  } catch (Exception e){
    return defaultValue;
  }
}

现在,以前的开发人员始终使用returnedValue = parseDouble(someString, -99);之类的默认值和if(returnedValue == -99)之类的检查来识别无效的解析结果。 (最后)添加的SonarQube服务器抱怨在==上使用double进行了此检查,我想用“正确的”检查代替这些检查。

处理此类情况的最佳实践是什么?

我个人会使用 parseDouble(someString, Double.NaN);,并因此检查支票if(Double.isNan(returnedValue)。这是可行的解决方案吗?

编辑: 我忘了提一下,实用程序类是不可编辑的(从我的角度来看),因此我正在研究如何轻松地“修复”现有代码。另外,添加第三方库也不错,但是(在当前时间)也是不可能的。

1 个答案:

答案 0 :(得分:0)

在过去,我也会使用NAN或POSITIVE_INFINITY或MAX_VALUE或其他未使用的东西。现在,我将使用Optional-class。由于转换,使用整数是不可靠的,而使用空值是Hoares十亿美元的错误:空值是否表示未初始化,未给出的错误?输入字符串为null还是被解析并且不是有效的双精度表示形式?

基本上,当出现解析错误或输入为空或用户输入了默认值时,您基本上不希望使用一种方法来返回默认值。您需要一种可以将信息归还给您的方法,无论是否存在错误,如果没有,则为已解析的值。 为了使您的代码更具可读性和易懂性,我将确切地编写这样一种方法,并在适当的地方使用它(而不是在任何地方使用复制粘贴的方法)。如果您不能将其放入现有的实用程序类中,请制作自己的其他实用程序类。 如果您使用的是Java 8,则可以使用Optional-class。如果不是,则编写自己的Optional(或从某些库中获取)。 这是实用程序方法:

Optional<Double> parseDouble(String input) { 
  try {    
    return Optional.of(Double.parseDouble(input));
  } catch (Exception e) {
    return Optional.empty();
  }
}

这里是使用方法:

String input = ...;
Optional<Double> parsedInput = parseDouble(input);
if (! parsedInput.isPresent()) {
    // print out warning and retry input or whatever
}
double convertedInput = parsedInput.value();

备注:

SonarQube也可能会抓到一个常见的“异常”。相反,您应该捕获NumberFormatException和NullPointerException。 当调用方需要知道确切的原因时,可以将方法getEmptyReason()添加到Optional(或派生类)中,然后在其中存储异常原因。但是我想在您的情况下,如果没有给出输入字符串(空或null),您想使用默认值;如果给定了值但无法解析,则想进行错误处理。在这种情况下,您可以使用:

Optional<Double> parseDouble(String input, double defaultValue) { 
  if (input == null || input.trim().length == 0) {
    return Optional.of(defaultValue);
  }
  try {    
    return Optional.of(Double.parseDouble(input));
  } catch (NumberFormatException e) {
    return Optional.empty();
  }
}