获取lambda的详细信息

要说啥?

Java8新增了lambda表达式,最常见的用法是配合Stream做集合操作。下面是一种类似彩蛋的东西可以妙用到某些场合。

一般用法,比如下面这样

Optional.of(1L).ifPresent(number -> {System.out.println(number);
});
复制代码

或者简化成这样

Optional.of(1L).ifPresent(System.out::println);
复制代码

有什么办法能获取到System.out::println里面的方法名字符串String methodName = "println"

啥效果?

执行代码

FnConverter<Foo> fnConverter = new FnConverter<>();
String fieldName = fnConverter.convertFnToString(Foo::getBar);
System.out.println("方法名:"+fieldName);
复制代码

输出

方法名:bar

怎么做?

第一步:定义一个FunctionalInterface(敲黑板,画重点extends Serializable

/*** @author Frank*/
@FunctionalInterface
public interface Fn<T> extends Serializable {Object apply(T source);
}
复制代码

第二布:准备个类(酱油)

import lombok.Data;/*** @author liuyuyu*/
@Data
public class Foo {private Integer bar;
}
复制代码

第三步:获取Fn的信息的工具类

  import java.beans.Introspector;import java.lang.invoke.SerializedLambda;import java.lang.reflect.Method;/*** @author Frank*/public class Reflections {private Reflections() {}public static String fnToFieldName(Fn fn) {try {Method method = fn.getClass().getDeclaredMethod("writeReplace");method.setAccessible(Boolean.TRUE);SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);String getter = serializedLambda.getImplMethodName();String fieldName = Introspector.decapitalize(getter.replace("get", ""));return fieldName;} catch (ReflectiveOperationException e) {throw new RuntimeException(e);}}}复制代码

画重点SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);

第四步:写个梨子跑起来

/*** @author liuyuyu*/
public class FnConverter<T> {public String convertFnToString(Fn<T> fn){return Reflections.fnToFieldName(fn);}public static void main(String[] args) {FnConverter<Foo> fnConverter = new FnConverter<>();String fieldName = fnConverter.convertFnToString(Foo::getBar);System.out.println("方法名:"+fieldName);}
}复制代码

Run

方法名:bar
复制代码

啥原理?

Serializable 是Java对象序列化的接口,凡是实现这个接口(interface是继承,也算)Java都要提供序列化和反序列化的方法(ObjectInputStream/ObjectOutputStream可能会让你想起点什么)。

但是lambda比较特殊,它是一个方法,可以认为是一个动作(或者说是功夫?比如九阴真经),没办法直接保存,Java提供了SerializedLambda这个类保存lambda的信息。

public final class SerializedLambda implements Serializable {private static final long serialVersionUID = 8025925345765570181L;private final Class<?> capturingClass;private final String functionalInterfaceClass;private final String functionalInterfaceMethodName;private final String functionalInterfaceMethodSignature;private final String implClass;private final String implMethodName;private final String implMethodSignature;private final int implMethodKind;private final String instantiatedMethodType;private final Object[] capturedArgs;//省略之后代码
}
复制代码

知道了这个隐藏(彩)特性(蛋),我们回头看看刚才黑板上画的重点

@FunctionalInterface //lambda
public interface Fn<T> extends Serializable //序列化接口
复制代码

两个条件满足

因为这个东西是个隐藏(彩)特性(蛋),我们不能直接获取到SerializedLambda。直接上反射!

SerializedLambda serializedLambda = (SerializedLambda) method.invoke(fn);

这样,我们就可以获取到lambda的方法名

还能干啥?

在框架设计的时候,很多场景要获取类的属性,Java8以前API设计的时候只能用字符串方式,如果是Java8,就可以避免字符串。

大家可以打开(骗星)栗子,直接运行代码感受一下。

Mybatis通用Mapper增强

lambda meta信息获取demo

转载于:https://juejin.im/post/5b0948d06fb9a07aa6323866

Java SAO操作-使用lambda代替字符串相关推荐

  1. STL之multiset中equal_range,multimap中的equal_range,bitset容器,string字符串操作,lambda表达式

     1multiset中用equal_range来遍历所有的元素 #include <set> #include <iostream> using namespace std ...

  2. 【Java文件操作(五)】从txt文件中读取字符串、乱码原因

    我的博客--Java文件操作系列 [Java文件操作(一)]递归打印文件目录 [Java文件操作(二)]删除文件夹,但保留其内部文件 [Java文件操作(三)]递归复制文件夹内所有文件 [Java文件 ...

  3. 精通lambda表达式:java多核编程_Java8 Lambda表达式和流操作如何让你的代码变慢5倍...

    有许许多多关于 Java 8 中流效率的讨论,但根据 Alex Zhitnitsky 的测试结果显示:坚持使用传统的 Java 编程风格--iterator 和 for-each 循环--比 Java ...

  4. 在Java中使用标准输入输出设备进行字符串,整数浮点数等 的输入输出操作

    在Java中使用标准输入输出设备进行字符串.整数浮点数等的输入输出操作 在Java语言中进行标准输入输出(键盘显示器)需要通过创建输入输出流对象的方式进行,一般情况下我们可以使用 BufferedRe ...

  5. Java Lambda 连接字符串

    Java Lambda 连接字符串 public class Menu {/*** 菜品名称*/private String name;/*** 菜品单价*/private Double price; ...

  6. java中操作字符串都有哪些类,他们之间有什么区别?

    java中操作字符串的类有哪些? String StringBuffer StringBuilder 区别 我们可以先看一下这几个类的继承关系图 从类的继承关系上来开的话,String和StringB ...

  7. java 中操作字符串都有哪些类?它们之间有什么区别?

    java 中操作字符串都有哪些类?它们之间有什么区别? String.StringBuffer.StringBuilder String : final修饰,String类的方法都是返回new Str ...

  8. java 拉姆表达式_Java8 lambda表达式10个示例

    Java 8 lambda表达式示例 转自importNew 原文链接 例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现R ...

  9. Java 函数式编程和 lambda 表达式

    为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...

最新文章

  1. windows下安装mongodb步骤
  2. 【深度学习mmdetection错误】——mmdetection 运行报错KeyError:‘ConvWS is already registered in conv layer‘
  3. .Net Core3.0依赖注入DI
  4. LCA求解的四种模板
  5. python文件操作小总结
  6. linux中hadoop环境变量配置文件,Ubuntu中关于hadoop环境变量的设置方法
  7. C#中Redis封装的类
  8. 易观的大数据革命 分析师与机器人协同办公
  9. 浅谈SpringMVC之DispatcherServlet
  10. Android多媒体开发(3)————使用Android NKD编译havlenapetr-FFMpeg-7c27aa2
  11. php+jq+添加css,jq如何添加css样式?
  12. 易语言单窗口单ip软件源码_想要挣钱创收 那就用脚本操作手机群控软件啊
  13. matlab如何修改图例的颜色,在MATLAB图例中设置线条颜色?
  14. YY淘宝商品数据库设计(转)
  15. win7桌面背景地址
  16. Linux云计算架构师:SSHD服务搭建管理和防止暴力破解
  17. 现货黄金入门:初识心理
  18. FPGA_PCB 设计之一3.3V-LVTTL与3.3V-LVCMOS区别
  19. 零基础如何自学编程?用这6种方法就够了!
  20. 如何获取篮球比赛实时赔率

热门文章

  1. 使用vsphere平台部署xendesktop时注意事项。
  2. 黄聪:Python中的__metaclass__=type什么意思?
  3. 在windows上搭建一个ftp服务器
  4. Notepad++ 经常使用快捷键 (MEMO)
  5. 就像教育一样,本身作用巨大,当过度强化,就是扭曲了~
  6. hdu 1300(dp)
  7. 网络编程C#篇(二):Socket无连接简单实例
  8. 不同的二叉搜索树 II
  9. 微信小程序自定义波浪组件
  10. springboot中缓存技术的使用、原理及其运行流程