亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java Scala泛型(泛型方法,泛型類(lèi),泛型特質(zhì),上下界,協(xié)變、逆變、非變)

 更新時(shí)間:2023年04月03日 14:38:21   作者:Maverick_曲流觴  
泛型的意思是泛指某種具體的數(shù)據(jù)類(lèi)型, 在Scala中, 泛型用[數(shù)據(jù)類(lèi)型]表示. 在實(shí)際開(kāi)發(fā)中, 泛型一般是結(jié)合數(shù)組或者集合來(lái)使用的,這篇文章主要介紹了Scala泛型(泛型方法,泛型類(lèi),泛型特質(zhì),上下界,協(xié)變、逆變、非變),需要的朋友可以參考下

1. 泛型

泛型的意思是泛指某種具體的數(shù)據(jù)類(lèi)型, 在Scala中, 泛型用[數(shù)據(jù)類(lèi)型]表示. 在實(shí)際開(kāi)發(fā)中, 泛型一般是結(jié)合數(shù)組或者集合來(lái)使用的, 除此之外, 泛型的常見(jiàn)用法還有以下三種:

  • 泛型方法
  • 泛型類(lèi)
  • 泛型特質(zhì)

1.1 泛型方法

泛型方法指的是把泛型定義到方法聲明上, 即:該方法的參數(shù)類(lèi)型是由泛型來(lái)決定的. 在調(diào)用方法時(shí), 明確具體的數(shù)據(jù)類(lèi)型.

格式

def 方法名[泛型名稱(chēng)](..) = {
    //...
}

需求

定義方法getMiddleElement(), 用來(lái)獲取任意類(lèi)型數(shù)組的中間元素.

  • 思路一: 不考慮泛型直接實(shí)現(xiàn)(基于Array[Int]實(shí)現(xiàn))
  • 思路二: 加入泛型支持.

參考代碼

//案例: 泛型方法演示.
//細(xì)節(jié): 泛型方法在調(diào)用方法的時(shí)候 明確具體的數(shù)據(jù)類(lèi)型.
object ClassDemo01 {
  //需求: 用一個(gè)方法來(lái)獲取任意類(lèi)型數(shù)組的中間的元素
  //思路一:不考慮泛型直接實(shí)現(xiàn)(基于Array[Int]實(shí)現(xiàn))
  //def getMiddleElement(arr: Array[Int]) = arr(arr.length / 2)

  //思路二: 加入泛型支持
  def getMiddleElement[T](arr: Array[T]) = arr(arr.length / 2)

  def main(args: Array[String]): Unit = {
      //調(diào)用方法
      println(getMiddleElement(Array(1, 2, 3, 4, 5)))

      println(getMiddleElement(Array("a", "b", "c")))
  }
}

1.2 泛型類(lèi)

泛型類(lèi)指的是把泛型定義到類(lèi)的聲明上, 即:該類(lèi)中的成員的參數(shù)類(lèi)型是由泛型來(lái)決定的. 在創(chuàng)建對(duì)象時(shí), 明確具體的數(shù)據(jù)類(lèi)型.

格式

class 類(lèi)[T](val 變量名: T)

需求

  • 定義一個(gè)Pair泛型類(lèi), 該類(lèi)包含兩個(gè)字段,且兩個(gè)字段的類(lèi)型不固定.
  • 創(chuàng)建不同類(lèi)型的Pair泛型類(lèi)對(duì)象,并打印.

參考代碼

//案例: 泛型-演示泛型類(lèi)的使用.
//泛型類(lèi): 在創(chuàng)建對(duì)象的時(shí)候, 明確具體的數(shù)據(jù)類(lèi)型.
object ClassDemo02 {
  //1. 實(shí)現(xiàn)一個(gè)Pair泛型類(lèi)
  //2. Pair類(lèi)包含兩個(gè)字段,而且兩個(gè)字段的類(lèi)型不固定
  class Pair[T](var a:T, var b:T)

  def main(args: Array[String]): Unit = {
    //3. 創(chuàng)建不同類(lèi)型泛型類(lèi)對(duì)象,并打印
    var p1 = new Pair[Int](10, 20)
    println(p1.a, p1.b)

    var p2 = new Pair[String]("abc", "bcd")
    println(p2.a, p2.b)
  }
}

1.3 泛型特質(zhì)

泛型特質(zhì)指的是把泛型定義到特質(zhì)的聲明上, 即:該特質(zhì)中的成員的參數(shù)類(lèi)型是由泛型來(lái)決定的. 在定義泛型特質(zhì)的子類(lèi)或者子單例對(duì)象時(shí), 明確具體的數(shù)據(jù)類(lèi)型.

格式

trait 特質(zhì)A[T] {
  //特質(zhì)中的成員
}

class 類(lèi)B extends 特質(zhì)A[指定具體的數(shù)據(jù)類(lèi)型] {
  //類(lèi)中的成員
}

需求

  • 定義泛型特質(zhì)Logger, 該類(lèi)有一個(gè)變量a和show()方法, 它們都是用Logger特質(zhì)的泛型.
  • 定義單例對(duì)象ConsoleLogger, 繼承Logger特質(zhì).
  • 打印單例對(duì)象ConsoleLogger中的成員.

參考代碼

//案例: 演示泛型特質(zhì).
object ClassDemo03 {
  //1. 定義泛型特質(zhì)Logger, 該類(lèi)有一個(gè)a變量和show()方法, 都是用Logger特質(zhì)的泛型.
  trait Logger[T] {
    //定義變量
    val a:T

    //定義方法.
    def show(b:T) = println(b)
  }

  //2. 定義單例對(duì)象ConsoleLogger, 繼承Logger特質(zhì).
  object ConsoleLogger extends Logger[String]{
    override val a: String = "張三"
  }

  //main方法, 作為程序的主入口.
  def main(args: Array[String]): Unit = {
    //3. 打印單例對(duì)象ConsoleLogger中的成員.
    println(ConsoleLogger.a)
    ConsoleLogger.show("10")
  }
}

2. 上下界

在使用泛型(方法, 類(lèi), 特質(zhì))時(shí),如果要限定該泛型必須從哪個(gè)類(lèi)繼承、或者必須是哪個(gè)類(lèi)的父類(lèi)。此時(shí),就需要使用到泛型的上下界

2.1 上界

使用T <: 類(lèi)型名表示給類(lèi)型添加一個(gè)上界,表示泛型參數(shù)必須要從該類(lèi)(或本身)繼承.

格式

[T <: 類(lèi)型]

例如: [T <: Person]的意思是, 泛型T的數(shù)據(jù)類(lèi)型必須是Person類(lèi)型或者Person的子類(lèi)型

需求

  • 定義一個(gè)Person類(lèi)
  • 定義一個(gè)Student類(lèi),繼承Person類(lèi)
  • 定義一個(gè)泛型方法demo(),該方法接收一個(gè)Array參數(shù).
  • 限定demo方法的Array元素類(lèi)型只能是Person或者Person的子類(lèi)
  • 測(cè)試調(diào)用demo()方法,傳入不同元素類(lèi)型的Array

參考代碼

//案例: 演示泛型的上下界之  上界.
object ClassDemo04 {
  //1. 定義一個(gè)Person類(lèi)
  class Person

  //2. 定義一個(gè)Student類(lèi),繼承Person類(lèi)
  class Student extends Person

  //3. 定義一個(gè)demo泛型方法,該方法接收一個(gè)Array參數(shù),
  //限定demo方法的Array元素類(lèi)型只能是Person或者Person的子類(lèi)
  def demo[T <: Person](arr: Array[T]) = println(arr)

  def main(args: Array[String]): Unit = {
    //4. 測(cè)試調(diào)用demo,傳入不同元素類(lèi)型的Array
    //demo(Array(1, 2, 3))          //這個(gè)會(huì)報(bào)錯(cuò), 因?yàn)橹荒軅魅隤erson或者它的子類(lèi)型.

    demo(Array(new Person()))
    demo(Array(new Student()))
  }
}

2.2 下界

使用T >: 數(shù)據(jù)類(lèi)型表示給類(lèi)型添加一個(gè)下界,表示泛型參數(shù)必須是從該類(lèi)型本身或該類(lèi)型的父類(lèi)型.

格式

[T >: 類(lèi)型]

注意:

例如: [T >: Person]的意思是, 泛型T的數(shù)據(jù)類(lèi)型必須是Person類(lèi)型或者Person的父類(lèi)型如果泛型既有上界、又有下界。下界寫(xiě)在前面,上界寫(xiě)在后面. 即: [T >: 類(lèi)型1 <: 類(lèi)型2]

需求

  • 定義一個(gè)Person類(lèi)
  • 定義一個(gè)Policeman類(lèi),繼承Person類(lèi)
  • 定義一個(gè)Superman類(lèi),繼承Policeman類(lèi)
  • 定義一個(gè)demo泛型方法,該方法接收一個(gè)Array參數(shù),
  • 限定demo方法的Array元素類(lèi)型只能是Person、Policeman
  • 測(cè)試調(diào)用demo,傳入不同元素類(lèi)型的Array

參考代碼

//案例: 演示泛型的上下界之 下界.
//如果你在設(shè)定泛型的時(shí)候, 涉及到既有上界, 又有下界, 一定是: 下界在前, 上界在后.
object ClassDemo05 {
  //1. 定義一個(gè)Person類(lèi)
  class Person
  //2. 定義一個(gè)Policeman類(lèi),繼承Person類(lèi)
  class Policeman extends Person
  //3. 定義一個(gè)Superman類(lèi),繼承Policeman類(lèi)
  class Superman extends Policeman

  //4. 定義一個(gè)demo泛型方法,該方法接收一個(gè)Array參數(shù),
  //限定demo方法的Array元素類(lèi)型只能是Person、Policeman
  //          下界          上界
  def demo[T >: Policeman <: Policeman](arr: Array[T]) = println(arr)

  def main(args: Array[String]): Unit = {
    //5. 測(cè)試調(diào)用demo,傳入不同元素類(lèi)型的Array
    //demo(Array(new Person))
    demo(Array(new Policeman))
    //demo(Array(new Superman))     //會(huì)報(bào)錯(cuò), 因?yàn)橹荒軅魅? Policeman類(lèi)獲取它的父類(lèi)型, 而Superman是Policeman的子類(lèi)型, 所以不行.
  }
}

3. 協(xié)變、逆變、非變

在Spark的源代碼中大量使用到了協(xié)變、逆變、非變,學(xué)習(xí)該知識(shí)點(diǎn)對(duì)閱讀spark源代碼很有幫助。

  • 非變: 類(lèi)A和類(lèi)B之間是父子類(lèi)關(guān)系, 但是Pair[A]和Pair[B]之間沒(méi)有任何關(guān)系.
  • 協(xié)變: 類(lèi)A和類(lèi)B之間是父子類(lèi)關(guān)系, Pair[A]和Pair[B]之間也有父子類(lèi)關(guān)系.
  • 逆變: 類(lèi)A和類(lèi)B之間是父子類(lèi)關(guān)系, 但是Pair[A]和Pair[B]之間是子父類(lèi)關(guān)系.

如下圖:

在這里插入圖片描述

3.1 非變

語(yǔ)法格式

class Pair[T]{}
  • 默認(rèn)泛型類(lèi)是非變的
  • 即: 類(lèi)型B是A的子類(lèi)型,Pair[A]和Pair[B]沒(méi)有任何從屬關(guān)系 3.2 協(xié)變

語(yǔ)法格式

class Pair[+T]
  • 類(lèi)型B是A的子類(lèi)型,Pair[B]可以認(rèn)為是Pair[A]的子類(lèi)型
  • 參數(shù)化類(lèi)型的方向和類(lèi)型的方向是一致的。

3.3 逆變

語(yǔ)法格式

class Pair[-T]
  • 類(lèi)型B是A的子類(lèi)型,Pair[A]反過(guò)來(lái)可以認(rèn)為是Pair[B]的子類(lèi)型
  • 參數(shù)化類(lèi)型的方向和類(lèi)型的方向是相反的

3.4 示例

需求

  • 定義一個(gè)Super類(lèi)、以及一個(gè)Sub類(lèi)繼承自Super類(lèi)
  • 使用協(xié)變、逆變、非變分別定義三個(gè)泛型類(lèi)
  • 分別創(chuàng)建泛型類(lèi)對(duì)象來(lái)演示協(xié)變、逆變、非變

參考代碼

//案例: 演示非變, 協(xié)變, 逆變.
object ClassDemo06 {
  //1. 定義一個(gè)Super類(lèi)、以及一個(gè)Sub類(lèi)繼承自Super類(lèi)
  class Super               //父類(lèi)
  class Sub extends Super   //子類(lèi)

  //2. 使用協(xié)變、逆變、非變分別定義三個(gè)泛型類(lèi)
  class Temp1[T]            //非變
  class Temp2[+T]           //協(xié)變
  class Temp3[-T]           //逆變.

  def main(args: Array[String]): Unit = {
    //3. 分別創(chuàng)建泛型類(lèi)來(lái)演示協(xié)變、逆變、非變
    //演示非變.
    val t1:Temp1[Sub] = new Temp1[Sub]
    //val t2:Temp1[Super] = t1          //編譯報(bào)錯(cuò), 因?yàn)榉亲兪? Super和Sub有父子類(lèi)關(guān)系, 但是Temp1[Super] 和 Temp1[Sub]之間沒(méi)有關(guān)系.

    //演示協(xié)變
    val t3:Temp2[Sub] = new Temp2[Sub]
    val t4:Temp2[Super] = t3          //不報(bào)錯(cuò), 因?yàn)閰f(xié)變是: Super和Sub有父子類(lèi)關(guān)系, 所以Temp2[Super] 和 Temp2[Sub]之間也有父子關(guān)系.
                                      //Temp2[Super]是父類(lèi)型,   Temp2[Sub]是子類(lèi)型.

    //演示逆變
    val t5:Temp3[Super]  = new Temp3[Super]
    val t6:Temp3[Sub] = t5          //不報(bào)錯(cuò), 因?yàn)槟孀兪?  Super和Sub有父子類(lèi)關(guān)系, 所以Temp3[Super] 和 Temp3[Sub]之間也有子父關(guān)系.
                                    //Temp3[Super]是子類(lèi)型,   Temp3[Sub]是父類(lèi)型.
  }
}

到此這篇關(guān)于Scala泛型(泛型方法,泛型類(lèi),泛型特質(zhì),上下界,協(xié)變、逆變、非變)的文章就介紹到這了,更多相關(guān)Scala泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java8?Stream流的常用方法匯總

    Java8?Stream流的常用方法匯總

    Java8?API添加了一個(gè)新的抽象稱(chēng)為流Stream,可以讓你以一種聲明的方式處理數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于Java8?Stream流的常用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • idea創(chuàng)建SpringBoot項(xiàng)目時(shí)Type選maven?project和maven?pom有何區(qū)別

    idea創(chuàng)建SpringBoot項(xiàng)目時(shí)Type選maven?project和maven?pom有何區(qū)別

    Maven是一個(gè)Java工程的管理工具,跟其相同功能的工具如Gradle,下面這篇文章主要給大家介紹了關(guān)于idea創(chuàng)建SpringBoot項(xiàng)目時(shí)Type選maven?project和maven?pom有何區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • JAVA中SpringBoot啟動(dòng)流程分析

    JAVA中SpringBoot啟動(dòng)流程分析

    這篇文章主要介紹了JAVA中SpringBoot啟動(dòng)流程分析的相關(guān)資料,需要的朋友可以參考下
    2023-01-01
  • Java MongoDB數(shù)據(jù)庫(kù)連接方法梳理

    Java MongoDB數(shù)據(jù)庫(kù)連接方法梳理

    MongoDB作為一種介于關(guān)系型數(shù)據(jù)庫(kù)和非關(guān)系型數(shù)據(jù)庫(kù)之間的產(chǎn)品,它可以提供可擴(kuò)展的高性能的數(shù)據(jù)存儲(chǔ)解決方案,近些年來(lái)受到了開(kāi)發(fā)者的喜愛(ài)
    2022-08-08
  • java中double類(lèi)型運(yùn)算結(jié)果異常的解決方法

    java中double類(lèi)型運(yùn)算結(jié)果異常的解決方法

    下面小編就為大家?guī)?lái)一篇java中double類(lèi)型運(yùn)算結(jié)果異常的解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12
  • mybatis查詢(xún)字段為null設(shè)置為0的操作

    mybatis查詢(xún)字段為null設(shè)置為0的操作

    這篇文章主要介紹了mybatis查詢(xún)字段為null設(shè)置為0的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java實(shí)現(xiàn)多線(xiàn)程模擬龜兔賽跑

    Java實(shí)現(xiàn)多線(xiàn)程模擬龜兔賽跑

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)多線(xiàn)程模擬龜兔賽跑,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • 高效數(shù)據(jù)傳輸?shù)拿孛芪淦鱌rotobuf的使用教程

    高效數(shù)據(jù)傳輸?shù)拿孛芪淦鱌rotobuf的使用教程

    Protobuf(Protocol?Buffers)是由?Google?開(kāi)發(fā)的一種輕量級(jí)、高效的數(shù)據(jù)交換格式,它被用于結(jié)構(gòu)化數(shù)據(jù)的序列化、反序列化和傳輸,本文主要介紹了它的具體使用方法,需要的可以參考一下
    2023-05-05
  • Spring中的@Cacheable緩存注解詳解

    Spring中的@Cacheable緩存注解詳解

    這篇文章主要介紹了Spring中的@Cacheable緩存注解詳解,數(shù)據(jù)庫(kù)查找的流程是先要從磁盤(pán)拿到數(shù)據(jù),再刷新到內(nèi)存,再返回?cái)?shù)據(jù)。磁盤(pán)相比于內(nèi)存來(lái)說(shuō),速度是很慢的,為了提升性能,就出現(xiàn)了基于內(nèi)存的緩存,需要的朋友可以參考下
    2023-05-05
  • SpringBoot2整合Redis實(shí)現(xiàn)讀寫(xiě)操作

    SpringBoot2整合Redis實(shí)現(xiàn)讀寫(xiě)操作

    Redis,對(duì)于大家來(lái)說(shuō)應(yīng)該不陌生,是經(jīng)常使用的開(kāi)發(fā)技術(shù)之一。本文將結(jié)合實(shí)例代碼,介紹SpringBoot2整合Redis實(shí)現(xiàn)讀寫(xiě)操作,感興趣的小伙伴們可以參考一下
    2021-07-07

最新評(píng)論