[英]How to pass generic method reference as parameter?
我想将通用方法引用作为参数传递给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 <>)不适用于参数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);
}
Bar foobar = foo(bar, Bar::new);
是有效的,因为您引用了特定类的构造函数。
鉴于:
foo(foobar, T::new)
尝试引用泛型类型的构造函数。 那根本不可能。 记住类型擦除,在(非常)端,这里只有Object
,并且强制转换。 T::new
根本不表示有意义的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.