Lic*_*ger 3 java functional-programming java-8 functional-interface
首先,请耐心等待.大部分时间我在Scala(有时只在JVM端)或其他语言工作,所以我的Java(8)知识有点受限!
我必须重构的代码充满了空检查.我想让一些pojo的属性设置/覆盖更好一点,并且很高兴能够使用Java 8来完成工作.
所以我创造了这个:
private <T> void setOnlyIfNotNull(final T newValue, Consumer<T> setter) {
if(newValue != null) {
setter.accept(newValue);
}
}
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
setOnlyIfNotNull(newUserName, user::setName);
Run Code Online (Sandbox Code Playgroud)
junit4-test看起来像这样:
@Test
public void userName_isOnlyUpdated_ifProvided() {
User user = new User("oldUserName");
UserUpdateRequest request = new UserUpdateRequest().withUserName("newUserName");
service.updateUser(user, request); // This calls setOnlyIfNotNull behind the curtain. And it does invoke the setter ONLY once!
assertThat(user.getUserName()).isEqualTo("newUserName");
}
Run Code Online (Sandbox Code Playgroud)
这很有效.在我请同事进行代码审查之前,我对自己很满意.在解释我做了什么之后,他详细说明了他认为这不起作用,因为函数仍然没有Java中的一等公民,而User-pojo没有扩展FunctionalInterface.接口也是在类级别而不是功能级别上提供的.
现在我想知道,为什么测试工作,我在这里滥用了什么?天真我只是想象Java编译器知道setter的T setT(T value)
签名与a相同Consumer<T>
.
编辑:详细说明一下:如果我将测试更改为失败,例如,assertThat(user.getUserName()).isEqualTo("Something");
如果失败,则会按预期进行compareFailure!
该评论在以下几个方面是错误的:
FunctionalInterface
接口不是必需的.它只是一个编译器提示,当标记有此注释的内容不符合条件时(仅仅是一个抽象方法的接口)标记错误
如果使用此批注类型对类型进行批注,则编译器需要生成错误消息,除非:
- 类型是接口类型,而不是注释类型,枚举或类.
- 带注释的类型满足功能接口的要求.
但是,无论接口声明中是否存在FunctionalInterface注释,编译器都会将满足功能接口定义的任何接口视为功能接口.
User
应该是功能性的,它是Consumer
界面,它是功能性的.user::setFoo
它不是一个"原始"函数,它是一个构造,它创建一个实现Consumer
(在这种情况下)的对象,并调用user.setFoo()
任何传递的参数这种机制表面上类似于匿名内部类如何声明一个类并立即创建一个实例.(但其背后的机制存在重大差异.)但最有力的论据是,您的代码只能使用Java的官方和文档API来证明是有效的.所以说"但Java不支持这个"是一种奇怪的想法.