1. Log printing uses placeholders
1.1 The role of placeholders
In daily development, in order to facilitate problem location, we usually use logs to print out information. When an exception or other problem occurs in the program, you need to use the log to locate the problem.
Usually, we will directly output the value of variables or parameters in the log output, so when a problem occurs, we can more accurately locate the key point.
The following are common usages:
@Slf4j
public class Test2 {
public static void main(String[] args) {
cal(5);
// cal(0)
}
/**
* 计算100除以该数后等于多少
* @param x
*/
public static void cal(int x) {
int result = 0;
log.info("param: {}", x); //打印出相关参数
try {
result = 100/x;
log.info("100 div {} = {}", x, result); //输出结果
} catch (Exception e) {
log.info("exception occur, exception: {}", e);
}
}
}
1.2 Wrong use of placeholders
The above code looks fine at first glance, but when we pass in the parameter 0, check the log print results:
When you want to output the exception e, the information of e is indeed printed out, but the placeholder is not replaced by the information. Why?
1.3 Problem location
In the idea, the relevant description of the problem is also accurately given. This error means: the log statement in the code uses a placeholder, but there are not enough parameters provided in the log statement to fill the placeholder character .
Hey, but I obviously provided parameters e
, why is it useless?
After clicking into the source code, it suddenly dawned on me.
When the incoming parameter is of an abnormal type, it will go directly to the log printing logic without formatting the placeholder.
1.4 Correct usage
- You can not set a placeholder, so that the error message will still be output ( recommended )
catch (Exception e) {
log.info("exception occur", e);
}
- Use
e.getMessage()
the method to output only the information of the exception type
catch (Exception e) {
log.info("exception occur, excpetion: {}", e.getMessage());
}
1.5 Summary
When the exception information needs to be output to the log, {}
the exception information can be completely printed out without using placeholders.
2. Do not use return in finally
2.1 Problem statement
There is such a rule in the Alibaba JAVA development manual:
【强制】不要在finally块中使用return。
说明:finally块中的return返回后方法结束执行,不会再执行try块中的return语句。
Here is a simple code example:
@Slf4j
public class Test {
public static void main(String[] args) {
int result = testFinally();
log.info("result is {}", result); // 输出结果为2而不是1
}
public static int testFinally() {
int result = 0; // 初始化返回值变量
try {
result++;
return result; // 返回语句
} catch (Exception e) {
log.info("exception occur.", e);
} finally {
// 在finally块中执行一些操作
result++;
return result; // 在方法的最后返回结果
}
}
}
The printed results are as follows:
2.2 Correct usage
@Slf4j
public class Test {
public static void main(String[] args) {
int result = testFinally();
log.info("result is {}", result);
}
public static int testFinally() {
int result = 0; // 初始化返回值变量
try {
result++;
} catch (Exception e) {
log.info("exception occur.", e);
} finally {
// 做一些清理资源或执行必要的清理操作
}
return result;
}
}
2.3 Supplementary Notes
If neither try
the block nor catch
the block returns a value, then the statement finally
is used inside the block andreturn
不会
has no effect on the program . In this case, finally
the code in the block will only perform the task of cleaning up resources or performing necessary cleanup operations without affecting the return value of the function or method.
However, you should still avoid using statements inside blocks , even though there are no return values in try
blocks and blocks . Because using statements in blocks can confuse other developers or maintainers, and doesn't conform to usual coding practices.catch
finally
return
finally
return
Therefore, it is recommended to avoid finally
using statements in blocks as much as possible return
to maintain the clarity and readability of the code.
3. find after matches
3.1 Problem statement
One day, when I was doing log matching, I found a strange problem. Obviously I have successfully matched, but when I want to get out the key information, an exception is reported to me.
The code reproduction results are as follows:
public class Test2 {
public static void main(String[] args) {
String str = "username:aaa";
String regex = "username:(.*?)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
System.out.println("matches: " + matcher.matches()); // True
System.out.println("find: " + matcher.find()); //false
}
}
Off the big spectrum, I obviously can match successfully, but it tells me that no matching information can be found?
3.2 Problem location
Putting a breakpoint, it can be clearly seen that after the matches method is executed, the internal parameter value of the match object has changed.
Click into the source code of the find method, we can see that the start position found by the find method is the value of last.
The method matches()
will set the value of last to the length of the string. When find()
the method is executed, the pattern matching starts from the end, not from the beginning of the input sequence. Therefore, Matcher
calling a method on an object before matches
calling find
a method may result in find
the method not being able to find any matches.
3.3 Solutions
It's very simple, just use it find(0)
, reset and find the actual location.
public static void main(String[] args) {
String str = "username:aaa";
String regex = "username:(.*?)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
System.out.println("matches: " + matcher.matches()); //True
System.out.println("find: " + matcher.find(0)); //True
}