[精讚] [會員登入]
711

【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

你可能感興趣的文章

【Wicket】[Cookie]如何讀取和設定客戶端的Cookie 對於某些參數需要給予使用者,我們可以使用 Cookie 來讓客戶端記著,之後再跟伺服器裡的比對來達到驗證的目的

【C】(%c, %d)解決讀取字元時的緩衝區殘留 不解決就會莫名其妙地冒出一些莫名其妙的東西

【Arduino/LinkIt 7697】實作小小的 MQTT Publish & Subscribe 若是要多點對多點傳輸資料,那使用 MQTT 即可快速的達成我們所需的目的

【Python3】[Django] (Windows / Liunx) 如何從零開始創建一個網站 除了最基本的運作以外,還小小的加上了如何自導向特定目錄。

【Wicket】[Header]如何讀取來自客戶端地檔頭和傳送自訂擋頭至客戶端 當需要設定檔頭或是讀取來自客戶端的檔頭時,這些程式碼就很好用

【Minecraft】[CoreProtect|BungeeCord]如何重新命名世界或維度名稱 當只有一個伺服器的時候,問題往往處理起來非常簡單,但是一旦當伺服器成長至兩台以上,事情便開始有趣了起來

隨機好文

高捷少女:小穹與果仁巧克力㊥ 艾咪臉上泛起笑容說:「妳知道嗎?就跟花語一樣,每一種巧克力也都有各自的涵義:薄荷巧克力代表初戀;卡通巧克力代表天真爛漫;而果仁巧克力代表的是窩心,還有想陪伴對方的心情,這在德國是女生之間在慶生時會彼此

高捷少女:美麗島的守護者③ 小雅閉上眼睛,思索在高捷發生的點點滴滴。她心意已決,在高捷的日子的確也有快樂的部分,不過她相信換個方向是更好的決定。有關高捷的所有美好回憶,小雅決定保留在心裡就好,繼續在高捷工作只會讓自己更痛苦而已,

高捷少女:美麗島的守護者(終) 「我是她的師娘,妳一定就是艾米莉亞吧?小雅昨晚有跟我說到您。」「師娘?」艾米疑惑不解。

高捷少女:耐耐的新年驚喜② 「各位,我跟爸媽聊完了……」耐耐走進客廳,看到大家在看自己的相簿,臉蛋立刻紅了。「哇啊啊,不要看那個!」她三步併作兩步地走向少女們,將相簿拿走。「為什麼啊?小時候的耐耐很可愛啊。」婕兒不解地說。

婕兒──她的青春③ 「墮天使穹音!」婕兒拿出平底鍋。 耐耐憋著笑搖搖頭。「不是喔,她是我的……我的……」 「替身。」小穹小聲提醒忘記台詞的耐耐。