【问题标题】:Java Generics: using parameterized interface in method callsJava 泛型:在方法调用中使用参数化接口
【发布时间】:2018-06-28 12:42:59
【问题描述】:

我想存储一个函数以应用于类的任何实例。由于我想为不同的类执行此操作,因此我在存储和应用代码时使用了一个接口。但是我的类型变量有一些问题:

我有一个界面

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 表达式的错误。删除 lambda 表达式并没有解决问题。 另一个页面提示了 OpenJdk 中的一个错误,建议更改类型变量的顺序。由于我使用的是 java Function 类,所以我无法做到这一点。

我也尝试获取Oracle Jdk,但我不能在这台机器上做任何事情。

欢迎任何想法!

【问题讨论】:

    标签: java function generics interface abstract


    【解决方案1】:
    Function<SomeClass,Object> someFunction = a -> new Object();
    

    不是Function&lt;SomeInterface&lt;R&gt;,R&gt; 的实例。

    您可以执行 Georg Henkel suggests: 更改 someFunction 变量的类型;或者你可以在方法调用中内联 lambda,并隐藏类型声明:

    handler.someMethod(a -> new Object());
    

    或者,要在调用站点保留现有类型,请将方法签名更改为:

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

    但请注意,为了能够使用文字 null 以外的任何内容调用 someFunction.apply,您必须传入 S(或包含 S 的内容,例如 CollectionOptional) 作为附加的方法参数。

    如果您不需要调用someFunction.apply(问题是为什么需要它...),您可以删除S 类型变量,然后使用:

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

    【讨论】:

    • 谢谢!我现在跳过声明。作为一种解决方法,我使用了 Function someFunction = a -> new Object();并且没有任何警告或任何东西。但我认为,跳过声明“更好”。
    【解决方案2】:

    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();
    

    【讨论】:

    • 是的,这行得通!但是,这意味着我所有的调度程序都在使用 SomeInterface 而不是不同的类。所以这是我最后的手段。
    • someFunction 改为使用extends 的缺点是,除了null 之外,您无法向其传递任何内容。
    • 感谢您的建议和您投入的时间!按照安迪的建议,我现在跳过声明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多