递归调用方法但只记录第二次?

时间:2017-01-01 19:32:06

标签: java recursion urldecode

我有一个下面的方法,它对使用charset传递的值进行URL解码。

  public String decodeValue(String value, Charset charset) {
    if (!Strings.isNullOrEmpty(value)) {
      try {
        value = URLDecoder.decode(value, charset.name());
      } catch (UnsupportedEncodingException ex) {
        // log error
        return null;
      }
    }
    return value;
  }

现在,如果第一次URLDecoder.decode行抛出UnsupportedEncodingException,那么我想对下面三行运行相同的value

value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
value = value.replaceAll("\\+", "%2B");
value = URLDecoder.decode(value, charset.name());

如果然后再次URLDecoder.decode行抛出异常第二次,那么我将记录错误但仅第二次并返回空值,否则返回被解码的值。

最好和最优雅的方法是什么?

5 个答案:

答案 0 :(得分:1)

最简单的方法是创建一个包含额外标志的函数签名的私有版本。

  private String decodeValue(String value, Charset charset, boolean isFirstTime) {
    if (!Strings.isNullOrEmpty(value)) {
      try {
        value = URLDecoder.decode(value, charset.name());
      } catch (UnsupportedEncodingException ex) {
        if (isFirstTime) {
            value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
            value = value.replaceAll("\\+", "%2B");
            return decodeValue(value, charset.name(), false);
        } else {
            // log error
            return null;
        }
      }
    }
    return value;
  }

然后,第一次传递true并在递归调用中传递false。在函数内部,只有在传递true时才执行接下来的三行。

公开版可以通过true

  public String decodeValue(String value, Charset charset) {
       decodeValue(value, charset, true);
  }

答案 1 :(得分:1)

虽然它不是递归的,但你可以使用while循环和标志。

public String decode(String value, Charset charset) {
    boolean first = true;
    while(!Strings.isNullOrEmpty(value)) {
        try {
            return value = URLDecoder.decode(value, charset);
        } catch (UnsupportedEncodingException e) {
            if(first == false) {
                // Log error.
                return null;
            }
            value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B");
        }
        first = false;
    }
    return value;
}

答案 2 :(得分:0)

你走了:

 public String decode(String value, Charset charset) {
    if (!Strings.isNullOrEmpty(value)) {
      try {
        value = URLDecoder.decode(value, charset.name());
      } catch (UnsupportedEncodingException ex) {
        try {
        value = value.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
        value = value.replaceAll("\\+", "%2B");
        value = URLDecoder.decode(value, charset.name());
      } catch (UnsupportedEncodingException ex) {
        // log error
        return null;
      }
      }
    }
    return value;
  }

希望这能解决你的问题。

答案 3 :(得分:0)

添加标记是一个选项。是的,这是更容易的;但是很多人认为简单地说 flags :不好的做法。

你只是尽量减少这些事情。

换句话说:如果你有一个方法,对于第一次和后续的调用应该表现出不同;考虑在那里创建两个方法。当然,你尽可能地避免代码重复,但除非它变得昂贵,你至少应该考虑避免这样的标志参数。

答案 4 :(得分:0)

这是没有额外标志,重复代码,递归和循环的版本:

public String decodeValue(final String value, Charset charset) throws UnsupportedEncodingException {
    String result;
    if (!Strings.isNullOrEmpty(value)) {
        UnsupportedEncodingException[] lastException = new UnsupportedEncodingException[1];
        result = Stream.<Function<String, String>>of(
                Function.identity(),
                s -> {
                    s = s.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
                    s = s.replaceAll("\\+", "%2B");
                    return s;
                })
                .map(f -> f.apply(value))
                .map(appliedValue -> {
                    try {
                        return URLDecoder.decode(appliedValue, charset.name());
                    } catch (UnsupportedEncodingException e) {
                        lastException[0] = e;
                        return null;
                    }
                })
                .filter(Objects::nonNull)
                .findFirst()
                .orElseThrow(() -> lastException[0]);
    }
    return result;
}

这里我只使用2个函数:身份和函数进行字符串校正。然后我将这些函数应用于初始字符串并尝试解码。如果第一次尝试成功,则代码将不会应用校正功能,只返回正确的结果。如果解码器在值修正后抛出异常,则“findFirst”将找不到任何值。然后我们抛出最后一次捕获的异常。