我想编写一个具有泛型方法的功能非泛型接口的实现。该实现必须是内联的,简洁的。
作为简化的示例
@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
的方法的通用接口。)
是否有一种变通方法,而无需回到匿名内部类的冗长程度?
显然有一个类似的问题“ Cannot convert functional interface with generic method into lambda expression”,但这源于使用名为Integer
的类型参数,而不是诸如T
这样的常规参数,乔恩·斯凯特(Jon Skeet)接受的答案说他不知道我的问题的解决方案。
还有很长的讨论“ Functional interface confusion”,未能回答这个问题。不能是“最好的详细匿名内部类在这里”,可以吗?
答案 0 :(得分:1)
经过大量的实验和间接的尝试后,我有了一个解决方案。我的命名不太成功。
这是主意
清除? [修辞]
所以不能写
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);
}
}
我不认为我已经利用了类型系统中缺乏任何健全性。
(我可能应该在问题中添加一个更复杂的示例,以说明您为什么要这样做。)
答案 1 :(得分:0)
泛型lambda无效,但泛型方法引用合法。您可以通过创建辅助方法来减少匿名类的冗长程度:
public class Scratch {
Fn id = Scratch::id;
Fn nul = Scratch::nul;
Fn requiresNotNull = Objects::requireNonNull;
private static <R> R id(R arg) {
return arg;
}
private static <R> R nul(R arg) {
return null;
}
}