我想存储一个要应用于任何类实例的函数。因为我想为不同的类做这个,我在存储和应用代码时使用了一个接口。但我的类型变量存在一些问题:
我有一个界面
public interface SomeInterface<P>
实施班
public class SomeClass implements SomeInterface<Object>
以及处理程序
public class SomeHandler {
public <R> void someMethod(Function<SomeInterface<R>,R> someFunction) {}
}
代码
public void someTest() {
Function<SomeClass,Object> someFunction = a -> new Object();
SomeHandler handler = new SomeHandler();
handler.someMethod(someFunction); //error here
}
无效。
标记位置的错误是“没有类型变量的实例R存在,以便SomeClass符合SomeInterface”
我已经尝试使用抽象类而不是接口。这也不起作用。
我做了一些研究,发现了一个包含lambda表达式的bug。删除lambda表达式并没有解决问题。 另一页提示OpenJdk中的一个错误,建议更改类型变量的顺序。当我使用java Function类时,我无法做到这一点。
我也试图获得Oracle Jdk,但我不允许在这台机器上做任何事情。
欢迎任何想法!
答案 0 :(得分:0)
将someTest()
中的功能更改为:
Function<SomeInterface<Object>, Object> someFunction = a -> new Object();
更新,具体取决于您的评论:
您可以将处理程序方法概括为更类似的东西:
public <R> void someMethod(Function<? extends SomeInterface<R>, R> someFunction) {}
这允许您使用类似以下内容的函数:
Function<SomeOtherClass, MyObject> someFunction = a -> new MyObject();
答案 1 :(得分:0)
Function<SomeClass,Object> someFunction = a -> new Object();
不是Function<SomeInterface<R>,R>
的实例。
您可以执行Georg Henkel suggests:更改someFunction
变量的类型;或者你可以在方法调用中内联lambda,并隐藏类型声明:
handler.someMethod(a -> new Object());
或者,要将现有类型保留在呼叫站点,请将方法签名更改为:
public <R, S extends SomeInterface<R>>
void someMethod(Function<S, R> someFunction)
但请注意,为了能够使用文字someFunction.apply
以外的任何内容来调用null
,您必须传入S
(或包含S
的内容},如Collection
或Optional
)作为附加方法参数。
如果您不需要致电someFunction.apply
(问题就是您需要它的原因......),您可以删除S
类型变量,然后使用:
public <R> void someMethod(Function<? extends SomeInterface<R>, R> someFunction)