java - 如何将泛型方法引用作为参数传递?

标签 java generics functional-programming

我想将通用方法引用作为 java 方法中的参数传递。

仅作为示例,我准备了一些摘要

public abstract class AbstractFoobar{

    abstract String getLiteral();
}

及其扩展的 2 个类。类有 String 参数构造函数。

public class Bar extends AbstractFoobar{

    String literal;

    public Bar(String literal) { this.literal = literal; }

    public String getLiteral() { return literal; }
}

public class Foo extends AbstractFoobar{

    String literal;

    public Foo(String literal) { this.literal = literal; }

    public String getLiteral() { return literal; }
}

我有一个简单的通用方法来创建对象的新实例。根据函数创建者参数创建

public <T extends AbstractFoobar> T foo(T foobar, Function<String, T> creator) {
    return creator.apply("foo" + foobar.getLiteral());
}

当使用特定方法引用 Bar::new 执行方法 foo 时,此示例完美运行。

@Test
void test()
    Bar bar = new Bar("bar");
    Bar foobar = foo(bar, Bar::new);
    assertEquals(Bar.class, foobar.getClass());
    assertEquals("foobar", foobar.getLiteral());
}

但是我不知道如何通过包装方法fooGenerator传递引用方法

public <T extends AbstractFoobar> T fooGenerator(T foobar) {
    //#1 return foo(foobar, T::new);
    //#2 return foo(foobar, foobar.getClass().getConstructor(String.class));        
}

#1 编译器无法实例化类型 T

#2 方法 foo(..., Function<>) 不适用于参数构造函数<>

最佳答案

关于 Java 泛型的一个非常重要但从未得到足够强调的一点是,它们只是避免编写显式强制转换的一种奇特方法。它们不多不少。

所以,如果你不会写:

public AbstractFoobar fooGenerator(AbstractFoobar foobar) {
    return foo(foobar, /* something here, involving AbstractFoobar and casts */::new);
}

// Call site
Bar foobar = (Bar) foo(bar);

那么你就不能用泛型来做到这一点。并不存在这样的事情,因为构造函数不参与继承: AbstractFoobar::new 会创建 AbstractFoobar 的实例(如果可以实例化的话),而不是一个子类。

对于当前的 AbstractFoobar 定义,除了使用显式参数直接调用 foo 之外,没有什么比这更好的了。

<小时/>

使用单个参数实现此目的的唯一方法是如果 AbstractFoobar 具有工厂方法,例如

public abstract class AbstractFoobar<A extends AbstractFoobar<A>> {
    // ...
    abstract A newInstance(String arg);
}

public class Bar extends AbstractFoobar<Bar> {
    // ...
    Bar newInstance(String arg) { return new Bar(arg); }
}

然后你可以这样使用:

public <T extends AbstractFoobar<T>> T fooGenerator(T foobar) {
  return foo(foobar, foobar::newInstance);
}

关于java - 如何将泛型方法引用作为参数传递?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55723740/

相关文章:

c# - 通用快速排序算法

linq - 在 F# 中编写 batchesOf size seq 的最惯用方法

functional-programming - 在 map 内部使用 if 时如何处理 "if may be missing an else clause"?

java - 针对 XML 架构(XSD 文件)的通用 XML 文件 validator

clojure - 我如何从clojure中给定的两个值一个一个地调用一个函数

java - 不同类的不同日志级别

java - 如何从递归函数中提取基本情况返回?

java - 在 Java 中制作一个不可聚焦的窗口

Java Custom Sort Order Round Robin-ish 排序

java - 如何从通用枚举类型中检索常量的接口(interface)?