[英]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
的子類型, MyInterface
將func
強制轉換為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.