那些Java开发中遇到的问题 您所在的位置:网站首页 java后端开发是什么职业 那些Java开发中遇到的问题

那些Java开发中遇到的问题

2023-04-21 05:16| 来源: 网络整理| 查看: 265

1. 日志打印使用占位符 1.1 占位符的作用

在日常开发中,为了方便问题定位,我们通常使用日志打印输出信息时。当程序出现了异常或者其他问题,需要通过日志来定位问题所在。

通常,我们在日志输出中会直接输出变量或者参数的值,那么在出现问题时,就更能准确地定位到关键点所在。

以下是常见的使用方式:

@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 错误的使用占位符

上述的代码乍看之下没有问题,但是当我们传入参数0,查看日志打印结果:

image-20230414150318320

想要输出异常e时,e的信息确实打印了出来,但是占位符并没有被信息取代,这是为什么呢?

1.3 问题定位

image-20230414150438079

在idea中,也准确的给出了该问题的相关说明,这个错误的意思是:代码中的日志语句使用了一个占位符,但是在日志语句中并没有提供足够的参数来填充这个占位符。

咦,可是我明明提供了参数e啊,为什么没用呢?

点进源码一看,恍然大悟。

image-20230414151122966

当传入的参数是异常类型时,就会直接走到日志打印逻辑,而不会进行占位符格式化处理。

1.4 正确用法 可以不设置占位符,这样错误信息依旧会输出(推荐) catch (Exception e) {    log.info("exception occur", e); } 复制代码

image-20230414151522024

使用e.getMessage()方法,仅把异常类型的信息输出 catch (Exception e) {    log.info("exception occur, excpetion: {}", e.getMessage()); } 复制代码

image-20230414151709326

1.5 总结

当需要将异常信息输出到日志时,无需使用占位符 {},也能将异常信息完整打印出来。

2. finally中不要使用return 2.1 问题说明

image-20230413111732867

在阿里巴巴JAVA开发手册中有这么一条准则:

【强制】不要在finally块中使用return。 说明:finally块中的return返回后方法结束执行,不会再执行try块中的return语句。 复制代码

以下是一个简单的代码示例:

@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; // 在方法的最后返回结果       }   } } 复制代码

打印结果如下:

image-20230414152809469

2.2 正确用法 @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 补充说明

如果在try块和catch块中都没有返回值,那么在finally块中使用return语句并不会对程序产生任何影响。在这种情况下,finally块中的代码只会执行清理资源或执行必要的清理操作的任务,而不会影响函数或方法的返回值。

但是,即使在try块和catch块中没有返回值,还是应该避免在finally块中使用return语句。因为在finally块中使用return语句可能会给其他开发人员或维护人员带来困惑,并且不符合通常的编码惯例。

因此,建议尽可能避免在finally块中使用return语句,以保持代码的清晰度和可读性。

3. matches后再find 3.1 问题说明

某一天,我在进行日志匹配的时候,发现一段诡异的问题。明明我都匹配成功了,但是当我想取出关键信息时,却给我报了异常。

代码复现结果如下:

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   } } 复制代码

离了大谱,我明明都能匹配成功,却告诉我找不到匹配的信息?

3.2 问题定位

打上断点,可以很明显的看到,执行了matches方法后,match对象的内部参数值发生了变化。

image-20230414171801728

image-20230414171850331

点进find方法源码,我们可以看到,find方法查到的开始位置,就是last的值。

image-20230414172037243

而matches()方法会将last的值置为字符串的长度,当执行find()方法时,模式匹配是从结尾处开始查找,而不是从输入序列的开头开始查找。因此,如果在Matcher对象上先调用matches方法,再调用find方法,可能会导致find方法无法找到任何匹配项。

3.3 解决办法

非常的简单,只需要使用find(0),重置查找其实位置即可。

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 } 复制代码


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有