是否可以将任何接口都写成lamda表达式?一定得加注解@FunctionalInterface才可以吗?

文章讲述了在Java中,即使接口没有@FunctionalInterface注解,依然可以在JDK8及以上版本中使用Lambda表达式,只要接口只包含一个抽象方法。@FunctionalInterface注解用于标记函数式接口,提供编译时检查功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先答案肯定是不对的,首先我们要知道这个注解的原生意义是什么,是否有说明必须得加这个注解才可以写lamda表达式。我们来看一下源码中对这个注解的description说明。

大概的翻译就是:

在Java中,@FunctionalInterface注解用于标记一个接口是函数式接口。函数式接口指的是只包含一个抽象方法的接口,它可以被用作Lambda表达式或方法引用的类型。

使用@FunctionalInterface注解有以下作用:

  1. 明确标识:通过在接口上添加该注解,明确表明该接口是函数式接口,以便其他开发者清晰地了解该接口的设计意图。
  2. 编译检查:编译器会检查带有@FunctionalInterface注解的接口,确保其只包含一个抽象方法。如果接口包含多个抽象方法,编译器将报错。

现在我们来举个例子验证一真伪,是否一定得加@FunctionalInterface注解才能使用lamda表达式,顺便验证源码解释对不对。

现在我建了一个package,name叫做traning4_fun_interface,下面有一个vo包,存放了UserVo.

还有一个Test测试类。一个UserService接口。

UserService是我自己创建的一个接口。

这个接口由@FunctionalInterface注解修饰。

UserVo是一个实体类,为了方便,我只声明了两个变量,一个是name一个是address

现在我们创建一个Test类进行测试。并调用。

运行结果:

控制台打印的这一串是什么意思呢?

其实就是因为我的UserVo没有重写toString()方法,所以它默认打印的是Object的toString()方法,不信我们在IDEA中通过快捷键CRTL+SHIFT+N搜索一下Object类。找到toString()方法。

其实lamada表达式等同于这样写:

所以如果你的jdk版本不是8以上的话,其实就得这样写。不能使用lamda表达式。本来对于接口,我们必须创建一个实现类,然后再通过Interface i = new InterfaceImpl(),然后再去调用i对象的方法。所以这种方法也叫做匿名内部类。所以以后遇到一些函数的参数是一个接口对象的话,同时这个接口只有一个抽象方法或者是@FunctionalIterface注解修饰的话,如果是jdk8以上版本的话,我们可以直接使用lamda表达式,然后再作为函数的参数,比如这个例子

我多加了三个类,一个是dto包下的Customer实体类;一个是CustomerService接口;一个是SysOperationLog;

我们先看下一下SysOperationLog这个类做了什么。

看到了这是一个系统操作日志类,模拟对客户的数据进行日志记录。

然后有一个静态方法,需要传入一个函数,这个函数是一个CustomerService接口对象。然后在函数里面就会调用该接口对象的queryAll()方法。

所以这时候我们去看一下CustomerService接口中长什么样吧

只有一个queryAll方法,返回对象是Customer实体。

现在我们在Test测试类里面去感受一下,SysOperationLog的recordCustomerService()这个方法的使用。我们打开Test类,在main方法中我们这样编写代码:

看到没有,直接传入一个lamda表达式进去。因为这个方法要接收一个接口对象参数嘛,接口又不能直接new,只能创建一个实现类然后再new这个实现类,但是我们不想这么麻烦,我们其实也可以使用匿名内部类的方法,在前面面我也说到过,再者就是这种lamada表达式的方法,其实他就是匿名内部类的优雅简化法,它其实说白了,花括号里面的代码就是实现类的方法。如果不是jdk8以上版本的话,我们就推荐使用匿名内部类的方法,或者是直接创建一个实现类,然后再实现接口,再去new 实现类。

现在我们看看此时的CustomerService接口上面是没有@FunctionalInterface注解的,看看此时我使用了java8的lamda表达式的写法,是否也可以打印结果出来。我们来看一下运行结果。

运行结果:

成功打印了。所以验证了不一定只有@FunctionalInteface注解修饰的接口才能在java8的时候使用lamda表达式。它只是一种声明,必须只能有一个abstrac方法,同时给开发人员一种,“喔,这个接口我等一下使用的时候,我就可以使用lamda表达式。”这种惯性想法。

 其实,在很多的java8类,都有很多这种形式,我推荐大家去看一下java8新特性中的Stream流、Optional等等。里面有大量的方法都是这样,比如map()、flatMap()......

总结:

不加注解@FunctionalInterface注解的接口,在java8的时候也可以使用lamda表达式。这个

@FunctionalInterface注解主要用于标记一个接口是函数式接口。函数式接口指的是只包含一个抽象方法的接口,它可以被用作Lambda表达式或方法引用的类型。

使用@FunctionalInterface注解有以下作用:

  1. 明确标识:通过在接口上添加该注解,明确表明该接口是函数式接口,以便其他开发者清晰地了解该接口的设计意图。
  2. 编译检查:编译器会检查带有@FunctionalInterface注解的接口,确保其只包含一个抽象方法。如果接口包含多个抽象方法,编译器将报错。

最后:如果大家觉得这篇文章对你有帮助的话,希望给你免费的赞赞,谢谢大家 ,也祝各位码农在代码路上能够高歌猛进。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值