簡體   English   中英

如何通過泛型方法引用作為參數?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM