Problems encountered in Java development

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:

image-20230414150318320

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

image-20230414150438079

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.

image-20230414151122966

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);
}

image-20230414151522024

  • Use e.getMessage()the method to output only the information of the exception type
catch (Exception e) {
    
    
    log.info("exception occur, excpetion: {}", e.getMessage());
}

image-20230414151709326

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

image-20230413111732867

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:

image-20230414152809469

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 trythe block nor catchthe block returns a value, then the statement finallyis used inside the block andreturn不会 has no effect on the program . In this case, finallythe 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 tryblocks and blocks . Because using statements in blocks can confuse other developers or maintainers, and doesn't conform to usual coding practices.catchfinallyreturnfinallyreturn

Therefore, it is recommended to avoid finallyusing statements in blocks as much as possible returnto 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.

image-20230414171801728

image-20230414171850331

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.

image-20230414172037243

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, Matchercalling a method on an object before matchescalling finda method may result in findthe 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
}

From: Problems Encountered in Java Development - Nuggets

Guess you like

Origin blog.csdn.net/qq_34626094/article/details/130176921