【java】java中常用的代码技巧 教你如何编写优雅代码

发布于:2024-03-22 ⋅ 阅读:(150) ⋅ 点赞:(0)

前言:博主之前写了一篇博客 :
【java】 java开发中 常遇到的各种难点 思路方案
上述博客主要描述的是该如何解决疑难场景,接下来博主带来姊妹篇,将针对用常规方式写出来的代码不太好看、效率不太高的场景 阐述该如何编写一些更加优雅的代码。

只有一个键值对如何存取更方便

只有一个键值对的时候 也使用hashmap来存取,就会导致虽然只有一个entry ,但也必须 get(key) 或遍历entrySet来取值,那有没有什么办法 我们不用传入任何参数 也可以直接getKey呢?

我们可以使用java.util下的AbstractMap.SimpleEntry来解决这个问题:


AbstractMap.SimpleEntry<String,Integer> simpleEntry = new AbstractMap.SimpleEntry("csdn:孟秋与你", 18);
String key = simpleEntry.getKey();
Integer value = simpleEntry.getValue();

如何封装if的非空校验

(注:@valid不是阐述重点,主要讲述如何封装if )

什么叫封装if呢 比如我们要判断名字是否为空 常规写法:

if(StringUtils.isBlank(name){
  throw new RuntimeException("名字不能为空");
}

还可能需要校验住址:

if(StringUtils.isBlank(address){
  throw new RuntimeException("地址不能为空");
}

在很多业务场景中,可能需要大量的判断,那就会导致大量的if 以及大括号 ,非常占用代码行数,那我们该如何简化呢?可以如下的写一个方法:


public static void checkBlank(String param,String message){
	if(StringUtils.isBlank(param){
	  throw new RuntimeException(message);
	}
}

调用方使用:

// 假设类名为 Check
Check.checkBlank(name,"姓名不能为空");
Check.checkBlank(address,"地址不能为空");

这样在业务流程代码 就不会看到大量的if以及大括号了,当然 针对不同类型的参数进行非空校验、是否相等校验 按照checkBlank方法自己去拓展就好了。

Optional orElseThrow如何记录错误日志

我们传统的orElseThrow可能就是抛一个异常:

// 可以将() -> new RuntimeException("error msg") 封装,参考封装if的方式
Object o = Optional.ofNullable(null).orElseThrow(() -> new RuntimeException("error msg"));

有时候为null就是严重的业务异常 需要事后通过日志排查,我们可能需要记录详细的日志信息 我们只需要在箭头后面加上大括号,并在抛异常前记录日志即可 对lambda熟悉的同学应该比较容易想到,如果lambda不熟练可能会不知道如何写。

  Optional.ofNullable(null).orElseThrow(() -> {
            log.info("other error");
            return new RuntimeException("xxx");
        });
// 异常封装:
public static Supplier<RuntimeException> supplier(String bizMessage,String logMsg) {
        log.info(logMsg);
        return () -> new RuntimeException(bizMessage);
    }

如何避免字段名被修改无法感知问题 如何避免魔法值

某个类的字段名修改了 其它地方可能不知道 解决方法 : 使用Function转换 ,这样不仅可以避免下游无法感知字段名变更的问题 也可以避免魔法值。

让我们用个例子来说明是什么意思: 比如我们的Oper实体类里面 有一个ukKey字段,我们在某个地方 将ukKey作为key 存放到map中,某一天 团队中其他人修改了这个字段名,比如改成了uniqueKey,这个时候map的key值 极大可能就会被疏忽。

转换代码:

   Map<String,Integer> map = new HashMap<>();
   map.put(FunctionUtils.function2Str(Oper::getUkKey), 123456);

FunctionUtils 工具类
(这是博主多年前写的一段代码 也是博主非常为之骄傲的一段代码):


public class FunctionUtils <T>{
    /**
     * Description: 函数式参数转回String属性名
     * date: 2021/06/09 12:05
     * @param sFunctionField
     * @return
     * @author qkj
     */
     public static <T> String function2Str (SFunction<T, ?> sFunctionField) {
        Method writeReplace = null;
        try {
            // 函数式方法可以直接调用writeReplace
            writeReplace = sFunctionField.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        writeReplace.setAccessible(true);
        String fieldName = "";
        try {
            // 序列化
            Object object = writeReplace.invoke(sFunctionField);
            // 反序列化
            SerializedLambda serializedLambda = (SerializedLambda) object;
            String methodName = serializedLambda.getImplMethodName();
            String temp = methodName.substring(3);
            fieldName = temp.replaceFirst(temp.substring(0,1),temp.substring(0,1).toLowerCase());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        return fieldName;

    }

}

如何简洁的往list里面添加有限个数元素

按照常规写法,我们可能是先new ArrayList() ; 接着往list里面逐个add,这样也会导致add的行数较多;我们可以通过更简洁的方式:

 List<Integer> list = Arrays.asList(1, 2, 3);
// >= jdk9 还可以通过List.of的方式
List<Integer> list1 = List.of(1, 2, 3);

注意:上述方式的list都不能remove 是不可变的,我们一般都过这种方式添加元素 基本上都是作为返回结果的 业务上已经确保不会remove了。

Arrays.asList原因简述: Arrays.asList返回的是Arrays类的内部类ArrayList ,这个ArrayList和我们常用的java.util.ArrayList是同名,但它是实现AbstractList的,且没有重写remove方法。
我们可以看看AbstractList的源码:

在这里插入图片描述

List.of 也是类似的,就不再分析了。

待续… 关注博主的同学可能比较清楚 博主的待续是真的有后续的 会动态更新
(本文原创:csdn 孟秋与你)

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到