[英]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.