大家好,這裡是還在 Java 裡持續有新發現的小編過路君子
近期開始對 Java 中的 interface 感興趣,interface 的寫法邏輯又不同於一般我們在寫 Java
直接看程式碼:
import java.util.Objects;
import java.util.ArrayList;
public class Main
{
// @param <T>: the type of the input to the function
// @param <R>: the type of the plane array result of the function
//
//
// e.g. PlaneArrayFunction<String, Boolean> example;
//
// We need input a String value,
// and we gonna get the return value which type is ArrayList<ArrayList<Boolean>>.
@FunctionalInterface
public interface PlaneArrayFunction<T, R>
{
public ArrayList<ArrayList<R>> apply(T t);
// @param <V>: the type of input to the {@code before} function,
// and to the composed function
default <V> PlaneArrayFunction<V, R> compose(PlaneArrayFunction<? super V, ? extends T> before)
{
Objects.requireNonNull(before);
return (V v) ->
{
ArrayList<ArrayList<T>> repeater = before.apply(v);
// For test, so we didn't do anything.
return new ArrayList<ArrayList<R>>();
};
}
}
public static void main(String[] args) {}
}
從上面的程式碼我們可以很清楚地發現,該泛型吃兩個變數型態,分別是 T 和 R。
其中 T 為傳入值型態,R 為回傳二維陣列的基礎型態。
也就是說我們雖然宣告為 R,但最終我們的執行結果型態卻是 ArrayList<ArrayList<R>> 的資料型態。
這樣講似乎仍然太謎語人,舉個實際的例子,但為了方便理解,小編將其適度簡化。
假設小編這樣宣告:PlaneArrayFunction<String, Integer> func = ...;。
當我們執行 func.apply(7) 的時候會取得一個 ArrayList<ArrayList<String>> 這樣。
但是當我們編譯以上程式碼的時候,卻得到以下的錯誤:
Main.java:28: error: incompatible types: ArrayList<ArrayList<CAP#1>> cannot be converted to ArrayList<ArrayList<R>>
ArrayList<ArrayList<R>> repeater = before.apply(v);
^
where T,R are type-variables:
T extends Object declared in interface PlaneArrayFunction
R extends Object declared in interface PlaneArrayFunction
where CAP#1 is a fresh type-variable:
CAP#1 extends T from capture of ? extends T
這就神奇了,竟然 ArrayList<ArrayList<T>> 接不住 ArrayList<ArrayList<? extends T>>。
長話短說,是因為 ArrayList<T> 並不繼承 ArrayList<? extends T>。
那 ArrayList<T> 繼承誰呢?對,就是 List<T>,而非 List<? extends T>。
這兩個物件雖然很像,但對於 Java 來說是兩個完全不同的東西,固當然無法接住。
後記
那最後小編怎麼解決這個錯誤呢?很簡單也很暴力,直接限制死輸入資料型態就可以順利接住了。
從 ? extends T 改成 T 即可。
default <V> PlaneArrayFunction<V, R> compose(PlaneArrayFunction<? super V, T> before)