Java编程学习:SAO操作-使用lambda代替字符串!

Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。

给你学习路线:html-css-js-jq-javase-数据库-jsp-servlet-Struts2-hibernate-mybatis-spring4-springmvc-ssh-ssm

Java编程学习:SAO操作-使用lambda代替字符串!_第1张图片

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" ?

啥效果?

Java编程学习:SAO操作-使用lambda代替字符串!_第2张图片

小编推荐一个学Java的学习裙【 七六零,二五零,五四一 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

执行代码

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

输出

方法名:bar

怎么做?

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

/** * @author Frank */@FunctionalInterfacepublic interface Fn extends Serializable { Object apply(T source);}

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

import lombok.Data;/** * @author liuyuyu */@Datapublic 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 { public String convertFnToString(Fn fn){ return Reflections.fnToFieldName(fn); } public static void main(String[] args) { FnConverter 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; //省略之后代码}

Java编程学习:SAO操作-使用lambda代替字符串!_第3张图片

小编推荐一个学Java的学习裙【 七六零,二五零,五四一 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

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

@FunctionalInterface //lambdapublic interface Fn extends Serializable //序列化接口

两个条件满足

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

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

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

Java编程学习:SAO操作-使用lambda代替字符串!_第4张图片
Java编程学习:SAO操作-使用lambda代替字符串!_第5张图片
Java编程学习:SAO操作-使用lambda代替字符串!_第6张图片

你可能感兴趣的:(Java编程学习:SAO操作-使用lambda代替字符串!)