lambda方法引用获取字段属性
作者:互联网
1、IGetter
import java.io.Serializable; @FunctionalInterface public interface IGetter<T> extends Serializable { Object get(T source); }
2、ISetter
import java.io.Serializable; @FunctionalInterface public interface ISetter<T, U> extends Serializable { void set(T t, U u); }
3、NjBeanUtils
import java.io.Serializable; import java.lang.invoke.SerializedLambda; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import lombok.extern.slf4j.Slf4j; /** * @author : whp * @describe : * @date : 2022/6/29 9:53 */ @Slf4j public class NjBeanUtils extends BeanUtil { /** * list 列表之间的拷贝 * @param sources * @param target * @return * @param <S> * @param <T> */ public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) { if(CollUtil.isEmpty(sources)){ return null; } return copyListProperties(sources, target, null); } /** * @author whp * 使用场景:Entity、Bo、Vo层数据的复制,因为BeanUtils.copyProperties只能给目标对象的属性赋值,却不能在List集合下循环赋值,因此添加该方法 * 如:List<AdminEntity> 赋值到 List<AdminVo> ,List<AdminVo>中的 AdminVo 属性都会被赋予到值 * S: 数据源类 ,T: 目标类::new(eg: AdminVo::new) */ public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, NjBeanUtilsCallBack<S, T> callBack) { List<T> list = new ArrayList<>(sources.size()); for (S source : sources) { T t = target.get(); copyProperties(source, t); list.add(t); if (callBack != null) { // 回调 callBack.callBack(source, t); } } return list; } /** * 通过getter的方法引用获取字段名 */ public static <T> String convertToFieldName(IGetter<T> fn) { try { SerializedLambda lambda = getSerializedLambda(fn); String methodName = lambda.getImplMethodName(); String prefix = null; if (methodName.startsWith("get")) { prefix = "get"; } else if (methodName.startsWith("is")) { prefix = "is"; } if (prefix == null) { log.error("无效的getter方法: " + methodName); } return toLowerCaseFirstOne(methodName.replace(prefix, "")); } catch (Exception e) { log.error("通过getter的方法引用获取字段名失败", e); return null; } } /** * 通过setter的方法引用获取字段名 * @throws Exception */ public static <T, U> String convertToFieldName(ISetter<T, U> fn) { try { SerializedLambda lambda = getSerializedLambda(fn); String methodName = lambda.getImplMethodName(); if (!methodName.startsWith("set")) { log.error("无效的setter方法:" + methodName); } return toLowerCaseFirstOne(methodName.replace("set", "")); } catch (Exception e) { log.error("通过setter的方法引用获取字段名失败", e); return null; } } /** * 关键在于这个方法 */ private static SerializedLambda getSerializedLambda(Serializable fn) throws Exception { Method method = fn.getClass().getDeclaredMethod("writeReplace"); method.setAccessible(Boolean.TRUE); SerializedLambda lambda = (SerializedLambda) method.invoke(fn); return lambda; } /** * 字符串首字母转小写 */ private static String toLowerCaseFirstOne(String field) { if (Character.isLowerCase(field.charAt(0))) return field; else { char firstOne = Character.toLowerCase(field.charAt(0)); String other = field.substring(1); return new StringBuilder().append(firstOne).append(other).toString(); } } }
4、单元测试
public static void main(String[] args) { System.out.println(NjBeanUtils.convertToFieldName(ShopIndex::getAddress)); System.out.println(NjBeanUtils.convertToFieldName(ShopIndex::getCityId)); System.out.println(NjBeanUtils.convertToFieldName(ShopIndex::setMartId)); System.out.println(NjBeanUtils.convertToFieldName(ShopIndex::setMartLocation)); }
5、运行结果
address cityId martId martLocation
标签:return,String,List,引用,methodName,import,lambda,public,属性 来源: https://www.cnblogs.com/linjiqin/p/16588574.html