Java Generics:在方法调用中使用参数化接口

时间:2018-01-19 09:54:03

标签: java function generics interface abstract

我想存储一个要应用于任何类实例的函数。因为我想为不同的类做这个,我在存储和应用代码时使用了一个接口。但我的类型变量存在一些问题:

我有一个界面

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,但我不允许在这台机器上做任何事情。

欢迎任何想法!

2 个答案:

答案 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的内容},如CollectionOptional)作为附加方法参数。

如果您不需要致电someFunction.apply(问题就是您需要它的原因......),您可以删除S类型变量,然后使用:

public <R> void someMethod(Function<? extends SomeInterface<R>, R> someFunction)