[英]How to pass generic method reference as parameter?
I would like to pass generic method reference as a parameter in java method. 我想将通用方法引用作为参数传递给java方法。
Just for an example I have prepared some abstract 仅作为示例,我准备了一些摘要
public abstract class AbstractFoobar{
abstract String getLiteral();
}
and 2 classes that its extend. 和2个扩展的类。 Classes have String parameter constructor.
类具有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; }
}
I have a simple generic method that creates new instance of the Objects. 我有一个简单的通用方法,可以创建对象的新实例。 The creation bases on Function creator parameter
创建基于函数创建者参数
public <T extends AbstractFoobar> T foo(T foobar, Function<String, T> creator) {
return creator.apply("foo" + foobar.getLiteral());
}
This example works perfectly when the method foo is executed with specific method reference Bar::new. 当使用特定的方法引用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());
}
But I dont know how to pass the reference method through the wrapper method fooGenerator 但是我不知道如何通过包装方法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 Compiler cannot instantiate the type T #1编译器无法实例化类型T
#2 the method foo(..., Function<>) is not applicable for the argument Constructor<> #2方法foo(...,Function <>)不适用于参数Constructor <>
A very important, but never emphasized enough, point about Java generics is that they are just a fancy way to avoid writing explicit casts . 关于Java泛型的一个非常重要但从未强调过的要点是, 它们只是避免编写显式强制转换的一种理想方式 。 They are nothing more, nothing less.
他们仅此而已。
So, if you can't write: 所以,如果你不能写:
public AbstractFoobar fooGenerator(AbstractFoobar foobar) {
return foo(foobar, /* something here, involving AbstractFoobar and casts */::new);
}
// Call site
Bar foobar = (Bar) foo(bar);
then you can't do it with generics. 那么您将无法使用泛型。 And there isn't such a thing, because constructors do not participate in inheritance:
AbstractFoobar::new
would create an instance of AbstractFoobar
(if it could be instantiated), not a subclass. 而且没有这样的事情,因为构造函数不参与继承:
AbstractFoobar::new
将创建AbstractFoobar
的实例(如果可以实例化),而不是子类。
For you current AbstractFoobar
definition, you can't do anything better than just invoking foo
directly, with the explicit arguments. 对于您当前的
AbstractFoobar
定义,除了直接使用显式参数直接调用foo
,您无法做其他任何事情。
The only way you could do it with a single parameter is if the AbstractFoobar
had a factory method on it, eg 您可以使用单个参数执行此操作的唯一方法是,如果
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); }
}
which you could then use like: 然后可以像这样使用:
public <T extends AbstractFoobar<T>> T fooGenerator(T foobar) {
return foo(foobar, foobar::newInstance);
}
Bar foobar = foo(bar, Bar::new);
is valid because you reference the constructor for a specific class. 是有效的,因为您引用了特定类的构造函数。
Whereas: 鉴于:
foo(foobar, T::new)
tries to reference the constructor of a generic type. 尝试引用泛型类型的构造函数。 And that is simply not possible.
那根本不可能。 Remember about type erasure, in the (very) end, there are just
Object
s here, and casts. 记住类型擦除,在(非常)端,这里只有
Object
,并且强制转换。 T::new
simply does not denote something meaningful. T::new
根本不表示有意义的事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.