最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

1. 泛型

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

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

1.1 泛型方法

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

格式

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

需求

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

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

參考代碼

//案例: 泛型方法演示.
//細節(jié): 泛型方法在調(diào)用方法的時候 明確具體的數(shù)據(jù)類型.
object ClassDemo01 {
  //需求: 用一個方法來獲取任意類型數(shù)組的中間的元素
  //思路一:不考慮泛型直接實現(xiàn)(基于Array[Int]實現(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 泛型類

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

格式

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

需求

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

參考代碼

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

  def main(args: Array[String]): Unit = {
    //3. 創(chuàng)建不同類型泛型類對象,并打印
    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ù)類型是由泛型來決定的. 在定義泛型特質(zhì)的子類或者子單例對象時, 明確具體的數(shù)據(jù)類型.

格式

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

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

需求

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

參考代碼

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

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

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

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

2. 上下界

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

2.1 上界

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

格式

[T <: 類型]

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

需求

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

參考代碼

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

  //2. 定義一個Student類,繼承Person類
  class Student extends Person

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

  def main(args: Array[String]): Unit = {
    //4. 測試調(diào)用demo,傳入不同元素類型的Array
    //demo(Array(1, 2, 3))          //這個會報錯, 因為只能傳入Person或者它的子類型.

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

2.2 下界

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

格式

[T >: 類型]

注意:

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

需求

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

參考代碼

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

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

  def main(args: Array[String]): Unit = {
    //5. 測試調(diào)用demo,傳入不同元素類型的Array
    //demo(Array(new Person))
    demo(Array(new Policeman))
    //demo(Array(new Superman))     //會報錯, 因為只能傳入: Policeman類獲取它的父類型, 而Superman是Policeman的子類型, 所以不行.
  }
}

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

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

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

如下圖:

在這里插入圖片描述

3.1 非變

語法格式

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

語法格式

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

3.3 逆變

語法格式

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

3.4 示例

需求

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

參考代碼

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

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

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

    //演示協(xié)變
    val t3:Temp2[Sub] = new Temp2[Sub]
    val t4:Temp2[Super] = t3          //不報錯, 因為協(xié)變是: Super和Sub有父子類關(guān)系, 所以Temp2[Super] 和 Temp2[Sub]之間也有父子關(guān)系.
                                      //Temp2[Super]是父類型,   Temp2[Sub]是子類型.

    //演示逆變
    val t5:Temp3[Super]  = new Temp3[Super]
    val t6:Temp3[Sub] = t5          //不報錯, 因為逆變是:  Super和Sub有父子類關(guān)系, 所以Temp3[Super] 和 Temp3[Sub]之間也有子父關(guān)系.
                                    //Temp3[Super]是子類型,   Temp3[Sub]是父類型.
  }
}

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

相關(guān)文章

  • springboot項目整合druid數(shù)據(jù)庫連接池的實現(xiàn)

    springboot項目整合druid數(shù)據(jù)庫連接池的實現(xiàn)

    這篇文章主要介紹了springboot項目整合druid數(shù)據(jù)庫連接池的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • springboot默認日志框架選擇源碼解析(推薦)

    springboot默認日志框架選擇源碼解析(推薦)

    這篇文章主要介紹了springboot默認日志框架選擇源碼解析(推薦),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Spring Boot部署到Tomcat過程中遇到的問題匯總

    Spring Boot部署到Tomcat過程中遇到的問題匯總

    這篇文章主要給大家分享了關(guān)于Spring Boot部署到Tomcat過程中遇到的一些問題,文中將解決的方法介紹非常詳細,對同樣遇到這個問題的朋友具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-03-03
  • Java中double和float類型的區(qū)別與使用方法

    Java中double和float類型的區(qū)別與使用方法

    float和double都是用來表示浮點數(shù)的數(shù)據(jù)類型,但是它們之間有一些區(qū)別,這篇文章主要給大家介紹了關(guān)于Java中double和float類型的區(qū)別與使用方法的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • 使用java的Calendar對象獲得當前日期

    使用java的Calendar對象獲得當前日期

    本文給大家分享的是使用使用java的Calendar對象獲得當前日期的上幾個度開始、結(jié)束時間,主要思路是先獲得當前季度的開始和結(jié)束日期,在當前日期的基礎(chǔ)上往前推3個月即上個季度的開始和結(jié)束日期,十分的實用,小伙伴們可以參考下。
    2015-07-07
  • java中UDP簡單聊天程序?qū)嵗a

    java中UDP簡單聊天程序?qū)嵗a

    這篇文章主要介紹了java中UDP簡單聊天程序?qū)嵗a,有需要的朋友可以參考一下
    2013-12-12
  • SpringBoot2整合Redis緩存三步驟代碼詳解

    SpringBoot2整合Redis緩存三步驟代碼詳解

    這篇文章主要介紹了SpringBoot2整合Redis緩存三步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-03-03
  • MybatisPlus查詢條件空字符串和NULL問題背景分析

    MybatisPlus查詢條件空字符串和NULL問題背景分析

    文章詳細分析了MybatisPlus在處理查詢條件時,空字符串和NULL值的問題,MP 3.3.0及以上版本提供了多種解決方法,包括在Bean屬性上使用注解、全局配置等,推薦使用全局配置的方式來解決這個問題,以避免在SQL查詢中出現(xiàn)不必要的空字符串條件,感興趣的朋友跟隨小編一起看看吧
    2025-03-03
  • Spring案例打印機的實現(xiàn)過程詳解

    Spring案例打印機的實現(xiàn)過程詳解

    這篇文章主要介紹了Spring案例打印機的實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • 關(guān)于JAVA_HOME路徑修改之后JDK的版本依然不更改的解決辦法

    關(guān)于JAVA_HOME路徑修改之后JDK的版本依然不更改的解決辦法

    今天小編就為大家分享一篇關(guān)于JAVA_HOME路徑修改之后JDK的版本依然不更改的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04

最新評論

新竹县| 当涂县| 华亭县| 郓城县| 木兰县| 五常市| 柳林县| 泾源县| 太白县| 南川市| 龙海市| 鄱阳县| 乌海市| 宁陕县| 奉新县| 伊吾县| 南华县| 恩平市| 五大连池市| 江孜县| 凤凰县| 商丘市| 宜兴市| 邛崃市| 丽水市| 清涧县| 黄冈市| 靖宇县| 荔浦县| 永宁县| 宜良县| 珠海市| 拉萨市| 苍溪县| 叶城县| 科尔| 广昌县| 隆子县| 乌审旗| 渑池县| 区。|