[精讚] [會員登入]
1021

【Java】[debug]多維泛型的大坑

incompatible types error

分享此文連結 //n.sfs.tw/16412

分享連結 【Java】[debug]多維泛型的大坑@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2024-05-25 13:41:22 最後編修
2024-05-25 12:26:35 By 過路君子
 

大家好,這裡是還在 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)
END

你可能感興趣的文章

【Java】(Project Valhalla)關於Java未來重大的變革 讓 Java 再次偉大!Make Java Great Again!

【Linux】[CentOS 8]如何更新sudo指令 上次會想要更新sudo這個指令的時間應該是2017年了吧?轉眼間就2021了耶

【PaperMC】從 Waterfall 切換至 Velocity waterfall 已經停止支援,最後停留在支援 Minecraft 1.21.6,之後的 Minecraft 版本便不再支援

【Vim】解決貼上文字時出現過多空格的問題 換了新系統,有時候就算重裝軟體並且複製了設定檔也還是會出現非常奇怪的現象

【Maven】[Wicket](Java) 如何部署Wicket到Wildfly內 Wicket 是一個 Java 下的套件,換言之,我們的網頁伺服器後端是由 Java 來撰寫的

【MEGAcmd】[Linux] 如何解決Unable to connect to service: error=2 用了好久的軟體突然停止一切的運作了。

隨機好文

高捷少女:地下城的探險少女④ 耐耐突然抖了一下。「妳們聽到了嗎?」她說。「聽到什麼?」婕兒問。「那個腳步聲啊!」耐耐嚥了一下喉嚨,覺得有些害怕。「有一陣腳步聲經過,很小聲,但我還是聽到了。』「妳聽錯了吧……等等!」婕兒使終維持著將

高捷少女:地下城的探險少女⑤ 小穹寫好後,耐耐看了一遍。「我想我應該辦得到。」她說完跪坐在地上,然後把古箏安放在大腿上,並將樂譜放在前面的地板。「要開始囉。」耐耐閉上眼睛,深呼吸一口氣,小穹等人在一旁看著她,心中暗自替她打氣。

高捷少女:美麗島的守護者② 這是在亦晨離開前的下午拍的,當時亦晨在美麗島跟小穹艾米等人在美麗島散步,為離開前補充一些回憶,這時剛好經過的小雅被艾米抓過來,做為同樣是高捷新人的她倆一同拍了一張紀念照。說起來她跟亦晨並不太熟,不過也

高捷少女:耐耐的新年驚喜① 耐耐拿出手機。「我回來囉。」她說。幾分鐘後,木門緩緩打開。當它完全開啟的那一刻,小穹手中的包包掉到地上;艾米揉揉雙眼,確定自己看見的景象;婕兒的三魂七魄飛到了九霄雲外。

【日翻中歌詞】ピースサイン(Peace Sign) 那一天從我們的頭頂 輕掠而過的那架飛機 有點不可思議 還記得 為何呢?毫無意義