前言:博主之前写了一篇博客 :
【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 孟秋与你)