Java8获取lambda方法引用传入的方法名

java8的lambda表达式极大的简化了我们的代码,其中方法引用(method reference)更是增加了代码的可(zhuang)读(bi)性和进一步简化了代码。本文将通过简单的例子介绍如何获取方法引用传入的方法名和类名。

一、需求

在之前的文章中我们通过反射的方式编写了一个空值校验器。使用方式如下:

        check(user,"username","pasword");

这样的空值校验器在使用中会带来两个问题:
1、字符串容易输入错误,并且难以debug
(例如上面的password写成了pasword)
2、当对应model修改的时候不能同步的去更新对应的方法,或者容易产生遗漏

针对以上问题,
我们希望实现的效果:

        check(user::getUsername, user::getPassword);

二、直接上代码

首先定义一个函数式接口:

//函数式接口注解
@FunctionalInterface
public interface Function extends Serializable {
    //这里只接收无参方法
    Object get();

    //这个方法返回的SerializedLambda是重点
    default SerializedLambda getSerializedLambda() throws Exception {
        //writeReplace改了好像会报异常
        Method write = this.getClass().getDeclaredMethod("writeReplace");
        write.setAccessible(true);
        return (SerializedLambda) write.invoke(this);
    }

    default String getImplClass() {
        try {
            return getSerializedLambda().getImplClass();
        } catch (Exception e) {
            return null;
        }
    }

    default String getImplMethodName() {
        try {
            return getSerializedLambda().getImplMethodName();
        } catch (Exception e) {
            return null;
        }
    }
}

写一个以Function接口为参数的check方法,使用可变参数可以使方法更灵活

    public static void check(Function... functions) {
        for (Function fun : functions) {
            System.out.println("传入的实现类:" + fun.getImplClass());
            System.out.println("传入的方法名:" + fun.getImplMethodName());
            System.out.println("传入的参数值:" + fun.get());
            System.out.println("传入数据类型:" + fun.get().getClass());
        }
    }

写一个main方法并调用:

    public static void main(String[] args) {

        User user = new User()
                .setUsername("123")
                .setPassword("456");

        check(user::getUsername, user::getPassword);
    }

调用结果:
调用结果
这样就可以获得lambda方法引用的参数名了

需要注意的是,这样的写法是不能获取正确信息的:

        check(()->user.getUsername());

三、关于SerializedLambda

仔细观察函数式接口Function,我们继承了Serializable接口,使得Function接口可以序列化。而SerializedLambda是java8提供的一个新的类,继承了Serializable的函数式接口的实例可以获取一个属于它的SerializedLambda实例,SerializedLambda封装了原传入函数的一些信息,这样我们就可以通过SerializedLambda获取到方法的名称,类名等信息了。

关于SerializedLambda更多的方法可参考

本文到此结束,谢谢浏览!!

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
1. 获取返回值类型 在AspectJ中,可以使用`JoinPoint`对象的`getSignature()`方法获取到当前执行的方法的签信息,进而获取方法的返回类型。具体代码如下: ```java @AfterReturning(pointcut = "execution(* com.example.demo.service.UserService.getUser(..))", returning = "result") public void afterReturning(JoinPoint joinPoint, Object result) { Signature signature = joinPoint.getSignature(); if (signature instanceof MethodSignature) { MethodSignature methodSignature = (MethodSignature) signature; Class<?> returnType = methodSignature.getReturnType(); System.out.println("返回类型:" + returnType.getName()); } } ``` 2. Lambda表达式获取传入方法引用方法 Lambda表达式可以通过方法引用来传递方法引用,如果需要获取这个方法方法,可以使用Java8中添加的`MethodReference`类来实现。具体代码如下: ```java public interface UserService { void addUser(User user); } public class UserServiceImpl implements UserService { @Override public void addUser(User user) { System.out.println("addUser调用成功"); } } public class UserController { private UserService userService; public void setUserService(UserService userService) { this.userService = userService; } public void addUser(User user) { userService.addUser(user); } } public class MyAspect { @Before("execution(* com.example.demo.controller.UserController.addUser(..)) && args(user)") public void beforeAddUser(User user) { MethodReference<UserService> methodReference = UserService::addUser; String methodName = methodReference.getName(); System.out.println("方法:" + methodName); } } ``` 在`MyAspect`切面中,通过Lambda表达式将`UserService::addUser`传递给`MethodReference`类,然后通过`getName()`方法获取方法。需要注意的是,这个方法是`UserService.addUser`而不是`UserServiceImpl.addUser`,因为`MethodReference`是根据接口中的方法获取方法的。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值