java - 如何为泛型方法编写简洁的闭包?
问题描述
我想编写一个具有泛型方法的功能性非泛型接口的实现。实现需要是内联闭包并且简洁。
作为一个简化的例子
@FunctionalInterface interface Fn {
<R> R fn(R arg);
}
public class Scratch {
Fn id = arg -> arg;
//Fn nul = arg -> null;
//Fn requiresNonNull = ...
}
这使
/Scratch.java:5: error: incompatible types: invalid functional descriptor for lambda expression
Fn id = arg -> arg;
^
method <R>(R)R in interface Fn is generic
where R is a type-variable:
R extends Object declared in method <R>fn(R)
1 error
(实际上,参数将是一个泛型接口,其方法的返回类型为R
。)
有没有一种解决方法,而不需要回到匿名内部类的冗长之处?
有一个明显相似的问题,“无法将具有泛型方法的功能接口转换为 lambda 表达式”,但这源于使用类型参数调用Integer
而不是传统的 like T
,并且 Jon Skeet 接受的答案说他不知道我的解决方案问题。
还有一个很长的讨论,“功能接口混乱”,无法回答这个问题。不可能是“这里最好使用冗长的匿名内部类”,可以吗?
解决方案
经过大量的实验和间接,我有一个解决方案。我在命名方面不太成功。
这是想法
- 功能接口和单个抽象方法都没有类型参数。
- 功能接口接收带有类型参数但在方法参数中使用通配符的使用者。
- 消费者只是一个内部gubbins,但它确实有那个类型参数。它用于在执行通过封闭函数返回时存储结果。
- 消费者本身接收一个包含实际业务功能实例的功能接口,该实例属于参数化类型。
- 有一个默认方法将事物联系在一起,包括创建消费者。
清除?[修辞]
所以,而不是能够写
Fn id = arg -> arg;
我们至少可以写
Fn id = q -> q.q(arg -> arg);
这是一个 lambda lambda 工厂。
我们似乎已经用完了语法,不能写类似的东西
Fn id = Fn.Consumer::q(arg -> arg); // not valid syntax!
总而言之(主要表明我没有作弊)
import java.util.concurrent.atomic.*;
@FunctionalInterface interface Fn {
interface Instance<R> {
R fn(R arg);
}
interface Consumer<R> {
void q(Instance<R> gn);
}
void consume(Consumer<?> consumer);
default <R> R fn(R arg) {
AtomicReference<R> result = new AtomicReference<>();
this.consume((Instance<R> instance) -> { result.set(instance.fn(arg)); });
return result.get();
}
}
public interface Scratch {
Fn id = q -> q.q(arg -> arg);
Fn nul = q -> q.q(arg -> null);
public static void main(String[] args) {
String idStr = id.fn("cruel");
String nulStr = nul.fn("cruel");
System.err.println(idStr);
System.err.println(nulStr);
}
}
我认为我没有利用类型系统中任何缺乏健全性的问题。
(我可能应该在问题中添加一个更复杂的示例,以说明您为什么要这样做。)
推荐阅读
- mysql - MySQL变量分配不分配给变量 - 我做错了什么?
- proxy - 负载均衡 Fiddler 代理
- django - 使用 S3 存储桶中的对象创建 Django 对象
- android - 使用“this”在片段中调用上下文
- mule-component - Mulesoft的后台进程
- css - 如果输入获得焦点或输入包含任何文本,则移动文本
- python - 为什么我的代码会随机出现错误?
- javascript - 尝试过的二叉树示例将输出作为对象,我怎样才能将此对象值放入数组中以处理进一步的问题
- c# - WPF - 如何将点击事件添加到项目控件?
- firebase - 实时数据库中的查询(使用 LimitToLast)非常非常慢