亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > 綜合 > 正文

Kotlin中協變、逆變和不變示例詳解

2024-07-21 23:03:45
字體:
來源:轉載
供稿:網友

前言

Kotlin 泛型的基本語法類似于 Java ,不過出于型變安全,不支持 Java 中的<? extends T>,<?super T> 通配符型變約束,而是采用類似 C# 的 in,out 用于支持協變和逆變,這同時避免了處理子類型化,父類化的問題(即Java泛型中典型的List<T> 不是 List<Object>的子類型的問題);

基本的泛型語法可以參考官方中文文檔:https://www.kotlincn.net/docs/reference/

泛型實參的繼承關系對泛型類型的影響

協變:泛型類型與實參的繼承關系相同

逆變:泛型類型與實參的繼承關系相反

不變:泛型類型沒有關系

協變點:返回值類型是泛型參數類型

逆變點:入參類型是泛型參數類型

@UnsafeVariance:協變點違例,告訴編譯器,沒事,你就按照我的意思執行

1、泛型

什么是泛型?泛化的類型或者是類型的抽象,鴨子類型(看起來像鴨子,走起來也像鴨子,就是鴨子類型)在靜態語言中的一種靜態實現

1、抽象類,是這個類的本質,它是什么

2、接口,關心類能夠做什么,行為能力

舉兩個例子

兩個數的比較大小

// 需要有對比的功能,沒有的話就會報錯a<b//加入限制 Comparable 具有對比的功能fun<T:Comparable<T>> maxOf(a:T,b:T):T{ return if (a<b) b else a}

方法調用

val a=2val b=3val maxOf = maxOf(2, 3) println("shiming "+maxOf)

輸出結果

 shiming 3

讓一個類具備對比的能

data class Complex(val a:Double,val b:Double):Comparable<Complex>{ override fun compareTo(other: Complex): Int { return (value()-other.value()).toInt() } fun value():Double{ return a*a+b*b } override fun toString(): String { return "$a*$a+$b*$b="+(a*a+b*b) }}

方法調用

 val Complex1=Complex(4.0,5.0) val Complex2=Complex(5.0,6.0) println("shiming Complex1="+Complex1) println("shiming Complex2="+Complex2) println("shiming"+Complex1.compareTo(Complex2))

輸出結果

04-16 11:22:10.824 26429-26429/com.kotlin.demo I/System.out: shiming Complex1=4.0*a+5.0*b=41.004-16 11:22:10.824 26429-26429/com.kotlin.demo I/System.out: shiming Complex2=5.0*a+6.0*b=61.004-16 11:22:10.824 26429-26429/com.kotlin.demo I/System.out: shiming-20

通過Demo的測試的結果的發現:泛型不管你到底是什么,它只管你能夠做什么事情

定義多個泛型參數

kotlin中的例子

 (1..2).map { println("shiming $it=="+it) }/** * Returns a list containing the results of applying the given [transform] function * to each element in the original collection.  (1..2).map調用的底層的方法 */public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> { return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)}/** A function that takes 22 arguments. function中最多的參數22.一共有23個方法 */public interface Function22<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, in P22, out R> : Function<R> { /** Invokes the function with the specified arguments. */ public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R}

kotlin中的類傳入泛型

data class ComplexNumber< T : Number>(val a:T,val b:T){ override fun toString(): String { return "$a*$a+$b*$b" }}

泛型的實現的機制

何為偽泛型(Java 、Kotlin)?編譯完了,泛型就沒有了(真正的原因就是最開始寫Java編譯器的幾個人偷懶取巧,留下了歷史問題,Martin Odersky爆料。Martin Odersky是Typesafe的聯合創始人,也是Scala編程語言的發明者。)

//按照重載的定義這兩個方法應該編譯的過的,但是Java和kotlin編譯完了成了object或者是沒有fun needList(list:List<Double>){}fun needList(list:List<Int>){}

通過反編譯可以看到,臥槽我的泛型沒有了

 public static final void needList(@NotNull List list) {  Intrinsics.checkParameterIsNotNull(list, "list"); } public static final void needList(@NotNull List list) {  Intrinsics.checkParameterIsNotNull(list, "list"); }

kotlin,協變,逆變,不變

沒有編譯通過

何為真泛型(C#)?編譯完了,還在

如果把以上的代碼放在C#中,就不會報錯,原因是C#的泛型不僅存在于編譯器,也存在運行期

java1.5才有的泛型特性,迫于現實的需求!用的人太多,但是C#第一個版本也沒有泛型,但是用的人少,所以C#使用的是真泛型

但是有一種方式可以在編譯器得到泛型類型:

reified讓泛型參數具體化,定義在inline中 ,kotlin實現為偽泛型,需要這個關鍵字植入到調用出才可以

//inline inline可用內聯函數(inline function)消除這些額外內存開銷,//說白了就是在調用處插入函數體代碼,以此減少新建函數棧和對象的內存開銷!inline fun<reified T> getT(){ println("shiming"+T::class.java)}

調用

getT<String>()getT<Double>()//通過反編譯得到的結果,說白了,其實就是打印了,這樣永遠都不會丟失  String var21 = "shiming" + String.class;  System.out.println(var21);  var21 = "shiming" + Double.class;  System.out.println(var21);

得到

04-16 15:28:59.775 31782-31782/com.kotlin.demo I/System.out: shimingclass java.lang.String04-16 15:28:59.775 31782-31782/com.kotlin.demo I/System.out: shimingclass java.lang.Double

在實際工作中可以這樣用

data class Person(val name:String,val age:Int){ //重寫,得到json字符串 override fun toString(): String {  return "{name="+"/""+name+"/","+"age="+age+"}" }}//例子 通過inline把這個前面的代碼植入到后面// reified讓泛型參數具體化,定義在inline中 ,kotlin實現為偽泛型,需要這個關鍵字植入到調用出才可以inline fun <reified T> Gson.fromJson(json:String):T=fromJson(json,T::class.java)//模擬網絡請求返回的json數據,得到bean類 val person=Person("shiming",20) println("shiming "+person) val toString = person.toString() val person1= Gson().fromJson<Person>(toString) println("shiming person1"+person1)//上面一段代碼的反編譯的結果,和java是一樣的,執行的流程  Person person = new Person("shiming", 20);  String toString = "shiming " + person;  System.out.println(toString);  toString = person.toString();  Gson $receiver$iv = new Gson();  Person person1 = (Person)$receiver$iv.fromJson(toString, Person.class);  String var25 = "shiming person1" + person1;  System.out.println(var25);

具體的關系

f(⋅)是逆變(contravariant)的,當A≤B時有f(B)≤f(A)成立;

f(⋅)是協變(covariant)的,當A≤B時有成立f(A)≤f(B)成立;

f(⋅)是不變(invariant)的,當A≤B時上述兩個式子均不成立,即f(A)與f(B)相互之間沒有繼承關系。

協變

在kotlin中List不是Java中的List,它只是只讀的,查看源碼如下List<out E> ,看見Out就是協變的,只讀類型,List中根本沒有add的方法,不可添加元素

//out 協變 Number 是Int的父類,協變點函數得返回類型val numberList:List<Number> = listOf<Int>(1,58) public interface List<out E> : Collection<E> { // Query Operations override val size: Int override fun isEmpty(): Boolean //告訴編譯器 我知道,你不要管我知道怎么搞 override fun contains(element: @UnsafeVariance E): Boolean override fun iterator(): Iterator<E> // Bulk Operations override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean // Positional Access Operations /**  * Returns the element at the specified index in the list.、  返回值的類型是E  */ public operator fun get(index: Int): E // Search Operations /**  * Returns the index of the first occurrence of the specified element in the list, or -1 if the specified  * element is not contained in the list.  */ public fun indexOf(element: @UnsafeVariance E): Int /**  * Returns the index of the last occurrence of the specified element in the list, or -1 if the specified  * element is not contained in the list.  */ public fun lastIndexOf(element: @UnsafeVariance E): Int // List Iterators /**  * Returns a list iterator over the elements in this list (in proper sequence).  */ public fun listIterator(): ListIterator<E> /**  * Returns a list iterator over the elements in this list (in proper sequence), starting at the specified [index].  */ public fun listIterator(index: Int): ListIterator<E> // View /**  * Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive).  * The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.  *  * Structural changes in the base list make the behavior of the view undefined.  */ public fun subList(fromIndex: Int, toIndex: Int): List<E>}

逆變:Comparable接口

  //in 逆變 ,泛型的繼承關系相反 逆變點就是函數參數的類型 Any是Int的父類 val intComparable:Comparable<Int> = object :Comparable<Any>{      override fun compareTo(other: Any): Int {        return 0      }    }public interface Comparable<in T> {  public operator fun compareTo(other: T): Int}

不變:MutableList相當于Java中的|ArrayList,可讀可寫,不可變,泛型沒有in 或者是out ,泛型的繼承關系也沒有具體的關系,前面是后面的子類或者是后面是前面的子類,都是不成立。

kotlin,協變,逆變,不變

public interface MutableList<E> : List<E>, MutableCollection<E> {  override fun add(element: E): Boolean  override fun remove(element: E): Boolean  override fun addAll(elements: Collection<E>): Boolean  public fun addAll(index: Int, elements: Collection<E>): Boolean  override fun removeAll(elements: Collection<E>): Boolean  override fun retainAll(elements: Collection<E>): Boolean  override fun clear(): Unit  public operator fun set(index: Int, element: E): E  public fun add(index: Int, element: E): Unit  public fun removeAt(index: Int): E  override fun listIterator(): MutableListIterator<E>  override fun listIterator(index: Int): MutableListIterator<E>  override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>}

星投影:始終找最安全的解決方法,安全方式是定義泛型類型的這種投影,該泛型類型的每個具體實例化將是該投影的子類型

如果泛型類型具有多個類型參數,則每個類型參數都可以單獨投影。
例如,如果類型被聲明為 interface Function <in T, out U> ,可以想象以下星投影:

Function<*, String> 表示 Function<in Nothing, String> ;

Function<Int, > 表示 Function<Int, out Any?>

Function<, *> 表示 Function<in Nothing, out Any?> 。

可用的星投影的地方

 //out 協變 Number 是Int的子類,協變點函數得返回類型    val numberList:List<*> = listOf<Int>(1,58)    val any = numberList[1] //星投影,去找父類    //in 逆變 ,泛型的繼承關系相反 逆變點就是函數參數的類型    val intComparable:Comparable<*> = object :Comparable<Any>{      override fun compareTo(other: Any): Int {        return 0      }    }    //星投影,去找父類 Nothing    intComparable.compareTo()fun <T> hello(){}open class Hello<T>{}//這樣 就可以使用星投影class Hello33<T>//這樣也可以使用星投影class Hello2:Hello<Hello<*>>()class Hello332:Hello<Hello33<*>>()

在kotlin中調用java的類

    //這樣也可以使用星投影 val raw:Raw<*> = Raw.getRaw()public class Raw<T> {  @Override  public String toString() {    return "老子是Raw";  }  public static Raw getRaw(){    return new Raw();  }}

不可以使用星投影的地方

    //不變的話,就根本沒有繼承關系,沒有任何的關系 原因是這樣不安全//    val list1:MutableList<Number> = mutableListOf<Int>(1,5,4)    list1.add(BigDecimal(1244444444))//    val list2:MutableList<Int> = mutableListOf<Number>(1,5,4)    //泛型的實參不要使用星號//    val numberList11d:List<*> = listOf<*>(1,58)////    hello<*>()////    val hello: Any = Hello<*>()fun <T> hello(){}open class Hello<T>{}

安卓中一個MvpDemo,使用到了星投影和協變!

package com.kotlin.demo.star_demoimport org.jetbrains.annotations.NotNullimport java.lang.reflect.ParameterizedType/** * author: Created by shiming on 2018/4/14 15:08 * mailbox:lamshiming@sina.com *///Mvp 中的V層 超級接口interface IView<out P:Ipresenter<IView<P>>>{  val presenter:P}//P層的超級接口interface Ipresenter<out V:IView<Ipresenter<V>>>{//  @NotNull//  IView getView();  val view:V}abstract class BaseView<out P:BasePresenter<BaseView<P>>>:IView<P>{  override val presenter:P  init {    presenter= findPresenterClass().newInstance()    presenter.view=this  }  /**   * 得到相對于的Class的文件   */  private fun findPresenterClass():Class<P>{    //不知道,使用星投影去接收 相當于 Class thisClass = this.getClass();    var thisClass:Class<*> = this.javaClass//    while(true) {//      Type var10000 = thisClass.getGenericSuperclass();//      if(!(var10000 instanceof ParameterizedType)) {//        var10000 = null;//      }//      ParameterizedType var5 = (ParameterizedType)var10000;//      if(var5 != null) {//        Type[] var6 = var5.getActualTypeArguments();//        if(var6 != null) {//          var10000 = (Type)ArraysKt.firstOrNull((Object[])var6);//          if(var10000 != null) {//            Type var2 = var10000;//            if(var2 == null) {//              throw new TypeCastException("null cannot be cast to non-null type java.lang.Class<P>");//            }////            return (Class)var2;//          }//        }//      }//    }    //以下的代碼相當于上面的代碼    while (true){      (thisClass.genericSuperclass as? ParameterizedType)          ?.actualTypeArguments          ?.firstOrNull()          ?.let {            return it as Class<P>          }?.run{              thisClass=thisClass.superclass ?:throw IllegalAccessException()            }          }    }  }abstract class BasePresenter<out V:IView<BasePresenter<V>>>:Ipresenter<V>{  //lateinit 延遲初始化  //@UnsafeVariance 告訴編譯器 我很安全 不要管我  override lateinit var view:@UnsafeVariance V}class MainView:BaseView<MainPresenter>()class MainPresenter:BasePresenter<MainView>()class Mvp{  init {    MainView().presenter.let(::println)    //相當于下面的代碼//    BasePresenter var1 = (new MainView()).getPresenter();//    System.out.println(var1);    MainView().presenter.let { println("shiming P="+it) }    //相當于下面的代碼//    var1 = (new MainView()).getPresenter();//    MainPresenter it = (MainPresenter)var1;//    String var3 = "shiming P=" + it;//    System.out.println(var3);//    (new MainPresenter()).getView();  }}

輸出的結果是:shiming P=com.kotlin.demo.star_demo.MainPresenter@fc35795

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到kotlin教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品免费一区豆花| 欧美一级大胆视频| 97成人精品区在线播放| 国产精品丝袜久久久久久高清| 亚洲天堂网在线观看| 国产精品成人国产乱一区| 日本伊人精品一区二区三区介绍| 久久久久国产精品www| 国产精品av在线播放| 日韩中文在线观看| 精品久久久久久久久久久| 日韩美女中文字幕| 亚洲欧美在线第一页| 久久久久久国产精品| 精品色蜜蜜精品视频在线观看| 亚洲国产成人在线视频| 国产精品久久久久久久久免费| 久久国产精品久久精品| 久久不射热爱视频精品| 欧美色xxxx| 精品亚洲aⅴ在线观看| 亚洲偷熟乱区亚洲香蕉av| 一区二区欧美激情| 8x海外华人永久免费日韩内陆视频| 欧洲午夜精品久久久| 亚洲免费视频网站| 91免费福利视频| 欧美最猛性xxxxx免费| 中文字幕日韩av综合精品| 欧美午夜激情在线| 国产精品视频1区| 国色天香2019中文字幕在线观看| 成人黄色免费看| 亚洲香蕉成人av网站在线观看| 久久久久久久久久久久久久久久久久av| 国产91在线播放| 亚洲欧美日韩中文视频| 51精品国产黑色丝袜高跟鞋| 久操成人在线视频| 精品欧美aⅴ在线网站| 国产成人+综合亚洲+天堂| 一区二区欧美久久| 成人h视频在线观看播放| 亚洲91精品在线| 久久在线精品视频| 日韩av色综合| 国产精品视频yy9099| 久久久精品国产亚洲| 国产精品成人一区二区| 亚洲精品短视频| 中文字幕亚洲自拍| 色系列之999| 最近免费中文字幕视频2019| 在线免费观看羞羞视频一区二区| 视频在线一区二区| 68精品国产免费久久久久久婷婷| 日韩精品免费在线视频观看| 国产69久久精品成人| 亚洲精品99久久久久中文字幕| 日韩成人性视频| 国产精品久久久久国产a级| 欧美第一黄色网| 久久精品最新地址| 日韩亚洲在线观看| 精品国内产的精品视频在线观看| 国产精品视频中文字幕91| 亚洲一区二区三区四区在线播放| 国产91久久婷婷一区二区| 日本伊人精品一区二区三区介绍| 国产精品自拍偷拍| 国产精品白丝av嫩草影院| 最近2019中文字幕一页二页| 精品美女久久久久久免费| 国产91精品不卡视频| 欧洲成人性视频| 久久久久久久一区二区| 午夜精品视频在线| 麻豆成人在线看| 日韩美女视频免费看| 久久天堂av综合合色| 欧美色欧美亚洲高清在线视频| 欧美中文在线免费| 欧美精品在线视频观看| 久久视频精品在线| 国内精品久久久久久中文字幕| 国语自产精品视频在线看抢先版图片| 亚洲国产天堂网精品网站| 亚洲精品美女在线| 日韩欧美在线第一页| 96pao国产成视频永久免费| 在线视频日本亚洲性| 高清欧美性猛交xxxx| 亚洲精品美女在线观看播放| 欧美成人网在线| 国产视频精品久久久| 欧美中文在线视频| 久久久人成影片一区二区三区| 2024亚洲男人天堂| 性亚洲最疯狂xxxx高清| 久久中文字幕在线视频| 91亚洲精品一区| 一区二区三区无码高清视频| 亚洲字幕在线观看| 全球成人中文在线| 在线播放亚洲激情| 欧美亚洲国产成人精品| 韩国一区二区电影| 秋霞成人午夜鲁丝一区二区三区| 国产精品久久一| 欧美激情xxxx性bbbb| 国产精品美女久久| 91精品国产色综合| 亚洲欧美精品suv| 最新国产精品亚洲| 欧美在线观看www| 亚洲视频axxx| 欧美激情va永久在线播放| 欧美亚洲国产日韩2020| 国产精品第100页| 久久精品视频导航| 91亚洲精华国产精华| 97久久精品视频| 欧美性猛交xxxx免费看| 自拍偷拍免费精品| 国产精品美女免费视频| 国产日韩欧美一二三区| 国产精品流白浆视频| 久久男人资源视频| 国产精品自产拍在线观看| 91久久在线播放| 综合网日日天干夜夜久久| www.欧美精品一二三区| 亚洲第一网中文字幕| 亚洲黄色av女优在线观看| 亚洲自拍小视频| 日韩成人网免费视频| 国产91精品久久久久久| 久久久亚洲网站| 亚洲最新在线视频| 欧美激情2020午夜免费观看| 欧美激情精品久久久久久蜜臀| 97国产精品人人爽人人做| 成人国产精品日本在线| 国产精品吴梦梦| 亚洲变态欧美另类捆绑| 国产在线精品成人一区二区三区| 国产精品国产三级国产专播精品人| 国模私拍一区二区三区| 亚洲日本欧美日韩高观看| 成人av在线天堂| 色青青草原桃花久久综合| 日韩免费av一区二区| 国语自产精品视频在线看一大j8| 91日韩在线播放| 亚洲色图在线观看| 欧美精品www| 久久色在线播放| 欧美大片免费观看在线观看网站推荐| 国产精品亚洲精品| 亚洲自拍偷拍福利| www日韩欧美| 久久乐国产精品| 亚洲欧洲国产伦综合| 日韩av大片免费看|