我想在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; }
}
我有一个简单的通用方法来创建对象的新实例。基于Function creator参数的创建
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<>) 不适用于参数 Constructor<>
关于 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);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句