递归调用一个方法但只记录第二次?
recursively call a method but log only second time?
我有一个下面的方法,它对使用字符集传递的值进行 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
行第二次抛出异常,那么我将记录错误但仅第二次和 return 空值,否则 return 解码的值。
执行此操作的最佳且优雅的方法是什么?
最简单的方法是制作包含额外标志的函数签名的私有版本。
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
则只执行接下来的三行。
public版本可以通过true
.
public String decodeValue(String value, Charset charset) {
decodeValue(value, charset, true);
}
给你:
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;
}
希望这能解决您的问题。
添加标志是一个选项。是的,这是比较容易的;但很多人认为拥有 标志 只是口语:不好的做法。
你只是尽量减少这些事情。
换句话说:如果您有一个方法在第一次调用和后续调用中表现不同;考虑在那里创建 两个 方法。当然,您会尽可能避免代码重复,但除非它变得代价高昂,否则您至少应该考虑避免此类标志参数。
虽然它不是递归的,但您可以使用 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;
}
这是没有额外标志、重复代码、递归和循环的版本:
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 个函数进行流处理:标识和进行字符串更正的函数。然后我将这些函数应用于初始字符串并尝试解码。如果第一次尝试成功,则代码将不会应用更正功能,而只是 return 正确的结果。如果解码器在值校正后抛出异常,则 "findFirst" 将找不到任何值。然后我们抛出最后捕获的异常。
我有一个下面的方法,它对使用字符集传递的值进行 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
行第二次抛出异常,那么我将记录错误但仅第二次和 return 空值,否则 return 解码的值。
执行此操作的最佳且优雅的方法是什么?
最简单的方法是制作包含额外标志的函数签名的私有版本。
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
则只执行接下来的三行。
public版本可以通过true
.
public String decodeValue(String value, Charset charset) {
decodeValue(value, charset, true);
}
给你:
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;
}
希望这能解决您的问题。
添加标志是一个选项。是的,这是比较容易的;但很多人认为拥有 标志 只是口语:不好的做法。
你只是尽量减少这些事情。
换句话说:如果您有一个方法在第一次调用和后续调用中表现不同;考虑在那里创建 两个 方法。当然,您会尽可能避免代码重复,但除非它变得代价高昂,否则您至少应该考虑避免此类标志参数。
虽然它不是递归的,但您可以使用 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;
}
这是没有额外标志、重复代码、递归和循环的版本:
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 个函数进行流处理:标识和进行字符串更正的函数。然后我将这些函数应用于初始字符串并尝试解码。如果第一次尝试成功,则代码将不会应用更正功能,而只是 return 正确的结果。如果解码器在值校正后抛出异常,则 "findFirst" 将找不到任何值。然后我们抛出最后捕获的异常。