<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                上面我們看到了Kotlin中List的定義,它在泛型參數前面加了一個out關鍵詞,我們在心里大概猜想,難道這個List的泛型參數是可變的?確實是這樣的,**如果在定義的泛型類和泛型方法的泛型參數前面加上out關鍵詞,說明這個泛型類及泛型方法是協變,簡單來說類型A是類型B的子類型,那么`Generic<A>`也是`Generic<B>`的子類型**,比如在Kotlin中String是Any的子類型,那么`List<String>`也是`List<Any>`的子類型,所以`List<String>`可以賦值給`List<Any>`。但是我們上面說過,如果允許這種行為,將會出現類型不安全的問題。那么Kotlin是如何解決這個問題的?我們來看一個例子: ``` val stringList: List<String> = ArrayList<String>() stringList.add("kotlin") //編譯報錯,不允許 ``` 這又是什么情況,往一個List中插入一個對象竟然不允許,難道這個List只能看看?確實是這樣的,**因為這個List支持協變,那么它將無法添加元素,只能從里面讀取內容**。這點我們從List的源碼也可以看出: ``` public interface List<out E> : Collection<E> { override val size: Int override fun isEmpty(): Boolean override fun contains(element: @UnsafeVariance E): Boolean override fun iterator(): Iterator<E> override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean public operator fun get(index: Int): E public fun indexOf(element: @UnsafeVariance E): Int public fun lastIndexOf(element: @UnsafeVariance E): Int public fun listIterator(): ListIterator<E> public fun listIterator(index: Int): ListIterator<E> public fun subList(fromIndex: Int, toIndex: Int): List<E> } ``` 我們發現,**List中本來就沒有定義add方法,也沒有remove及replace等方法,也就是說這個List一旦創建就不能再被修改,這便是將泛型聲明為協變需要付出的代價**。那么為什么泛型協變會有這個限制呢?同樣我們用反證法來看這個問題,如果允許向這個List插入新對象,會發生什么?我們來看一個例子: ``` val stringList: List<String> = ArrayList<String>() val anyList: List<Any> = stringList anyList.add(1) val str: String = anyList.get(0) //Int無法轉換為String ``` 從上面的例子可以看出,**假如支持協變的List允許插入新對象,那么它就不再是類型安全的了,也就違背了泛型的初衷**。所以我們可以得出結論:**支持協變的List只可以讀取,而不可以添加**。其實從out這個關鍵詞也可以看出,out就是出的意思,可以理解為List是一個只讀列表。在Java中也可以聲明泛型協變,用通配符及泛型上界來實現協變:`<? extends Object>`,其中Object可以是任意類。比如在Java中聲明一個協變的List: ``` public interface List <? extends T> { ...... } ``` 但泛型協變實現起來非常別扭,這也是Java泛型一直被詬病的原因。很慶幸,Kotlin改進了它,使我們能用簡潔的方式來對泛型進行不同的聲明。 另外需要注意的一點的是:**通常情況下,若一個泛型類`Generic<out T>`支持協變,那么它里面的方法的參數類型不能使用T類型,因為一個方法的參數不允許傳入參數父類型的對象,因為那樣可能導致錯誤。但在Kotlin中,你可以添加@UnsafeVariance注解來解除這個限制,比如上面List中的indexOf等方法**。 上面介紹了泛型不變和協變的兩種情況,那么會不會出現第3種情況,比如類型A是類型B的子類型,但是`Generic<B>`反過來又是`Generic<A>`的子類型呢?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看