簡體   English   中英

將java.util.function.Function轉換為Interface

[英]Cast java.util.function.Function to Interface

在此(簡化)的例子,我可以創造我的MyInterface使用方法參照-object apply ,而是直接鑄造不起作用。

@Test
public void testInterfaceCast(){
    Function<String, Integer> func = Integer::parseInt;

    MyInterface legal = func::apply; // works
    MyInterface illegal = func; // error
}

public interface MyInterface extends Function<String, Integer>{}

第二個賦值給出了編譯器錯誤:

incompatible types: Function<String,Integer> cannot be converted to MyInterface

這個問題

我可以做一些泛型魔法,能夠將Function<T, R>轉換為接口嗎?

MyInterface illegal = func;的原因MyInterface illegal = func; 不起作用,是因為func被聲明為Function<String,Integer>類型的變量,它不是MyInterface的子類型。

MyInterface legal = func::apply; 作品如下。 你可能期望fun::apply的類型也是Function<String,Integer> ,但事實並非如此。 fun::apply的類型部分取決於編譯器期望的類型。 由於您在賦值上下文中使用它,因此編譯器需要一個類型為MyInterface ,因此在該上下文中, func::apply的類型為MyInterface 正是由於這個原因,方法引用表達式只能出現在賦值上下文,調用上下文和轉換上下文中(參見Java語言規范 )。

由於Function<String,Integer>不是MyInterface的子類型, MyInterfacefunc強制轉換為MyInterface會引發ClassCastException 因此,將Function<String,Integer>轉換為MyInterface方法是使用方法引用,就像您已經做過的那樣:

MyInterface legal = func::apply;

最重要的是,盡管所有漂亮的語法都表面上看起來如此,但Java並沒有采用結構類型; Liskov 命名類型的可替代性規則與以往一樣嚴格。 在你的現實代碼中,你調用Function.andThen ,它返回一些Function的實例,絕對不是MyInterface的實例。 所以當你寫作

MyInterface legal = func::apply;

你會得到另一個對象,它是MyInterface一個實例。 相比之下,當你寫作

MyInterface illegal = func;

您試圖將對現有Function的引用直接分配給illegal ,這會違反Liskov可替代性,即使它在結構上與類型匹配。 沒有任何技巧可以從根本上解決這個問題; 即使Java引入了一些新的語法糖,它會使它看起來像轉換,實際的語義仍然是轉換 (評估到另一個實例)。

由於此代碼段無法編譯,因此無法編譯:

Animal animal = new Animal();
Cat x = animal; //illegal assignment

即你暗示每只動物都可以成為一只貓。 編譯器沒有證據表明實際的超類實例在運行時確實是一只貓 ,因此會引發錯誤。

您必須將Integer::parseInt分配給MyInterface實例:

MyInterface func = Integer::parseInt;
MyInterface illegal = func;

因為func的類型是Function<String, Integer> (即MyInterface的超類型)。

事實是, 除非將它分配MyInterface變量, 否則 MyInterface在編譯時生成類型為MyInterface Integer::parseInt

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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