亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解Java/Scala泛型

發布時間:2021-11-04 14:59:13 來源:億速云 閱讀:165 作者:iii 欄目:編程語言

本篇內容介紹了“怎么理解Java/Scala泛型”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

泛型(Generics)是強類型編程語言中經常使用的一種技術。很多框架的代碼中都會大量使用到泛型,比如在Java中我們經常看到的:

List<String> strList = new ArrayList<String>();List<Double> doubleList = new LinkedList<Double>();

在這段代碼中,ArrayList就是一個泛型類,List就是一個泛型接口類,他們提供給開發者一個放置不同類型的集合容器,我們可以向這個集合容器中添加String、Double以及其他各類數據類型。無論內部存儲的是什么類型,集合容器提供給開發者的功能都是相同的,比如添加add,get等。有了泛型,我們就沒必要創建StringArrayList、DoubleArrayList等集合了,否則代碼量太大,維護起來成本極高。

在Java中,泛型一般有三種使用方式:泛型類,泛型方法和泛型接口類。一般使用尖括號<>來接收泛型參數。

Java泛型類

假如我們自己定義一個支持泛型的MyArrayList,這個列表類可以簡單支持初始化和數據寫入。只要在類名后面加上就可以讓這個類支持泛型,類內部的一些屬性和方法都可以使用泛型類型T。當然我們給這個類也可以添加多個泛型參數,比如

public class MyArrayList<T> {    private int size;    T[] elements;    public MyArrayList(int capacity) {        this.size = capacity;        this.elements = (T[]) new Object[capacity];    }    public void set(T element, int position) {        elements[position] = element;    }    @Override    public String toString() {        String result = "";        for (int i = 0; i < size; i++) {            result += elements[i].toString();        }        return result;    }    public static void main(String[] args){        MyArrayList<String> strList = new MyArrayList<String>(2);        strList.set("first", 0);        strList.set("second", 1);        System.out.println(strList.toString());    }}

我們也可以從父類中繼承并擴展泛型,比如Flink源碼中有這樣一個類定義,子類繼承了父類的T,同時自己增加了泛型KEY:

public class KeyedStream<T, KEY> extends DataStream<T> {  ...}

Java泛型接口類

Java泛型接口類的定義和Java泛型類基本相同。下面的代碼展示了List接口中定義subList方法,該方法截取原來列表的一部分。

public interface List<E> {    ...    public List<E> subList(int fromIndex, int toIndex);}

繼承并實現這個接口類的代碼如下:

public class ArrayList<E> implements List<E> {    ...    public List<E> subList(int fromIndex, int toIndex) {        subListRangeCheck(fromIndex, toIndex, size);        return new SubList(this, 0, fromIndex, toIndex);    }}

Java泛型方法

泛型方法可以存在于泛型類(包括接口類)中,也可以存在于普通的類中。

public class MyArrayList<T> {    ...    // public關鍵字和返回值E之間的<E>表明這是一個泛型方法    // 泛型方法中的類型E和泛型類中的類型T可以不一樣  public <E> E processElement(E element) {        ...        return E;    }}

從上面的代碼示例可以看出,public或private關鍵字和方法返回值之間的尖括號表示這是一個泛型方法。泛型方法的類型E和泛型類中的T可以不一樣,或者說,如果泛型方法是泛型類的一個成員,泛型方法既可以繼續使用類中的T,也可以自己定義新的類型E。

通配符

除了用表示泛型外,還有 這種形式。 被稱為通配符,用來適應各種不同的泛型。

泛型小結

對Java的泛型總結下來發現,雖然它的語法有時候讓人有些眼花繚亂,其本質是為了接受不同的數據類型,增強代碼的復用性。

我們可以在一個類里使用多個泛型,每個泛型一般使用大寫字母表示。Java為此提供了一些大寫字母使用規范:

  • T 代表一般的任何類。

  • E 代表元素(Element)或異常(Exception)。

  • K 代表鍵(Key)。

  • V 代表值(Value),通常與K一起配合使用,比如

Java的泛型給開發者提供了不少便利,尤其是保證了底層代碼簡潔性,因為這些底層代碼通常被封裝為一個框架,會有各種各樣的上層應用調用這些底層代碼進行特定的業務處理,每次調用都可能涉及泛型問題。比如,大數據框架Spark和Flink中都需要開發者基于泛型進行數據處理。

以上只對泛型做了一個簡單的介紹,實際上在具體使用時還有一些細節需要注意。

類型擦除

Java的泛型有一個遺留問題,那就是類型擦除(Type Erasure)。我們先看一下下面的代碼:

Class<?> strListClass = new ArrayList<String>().getClass();Class<?> intListClass = new ArrayList<Integer>().getClass();// 輸出:class java.util.ArrayListSystem.out.println(strListClass);// 輸出:class java.util.ArrayListSystem.out.println(intListClass);// 輸出:trueSystem.out.println(strListClass.equals(intListClass));

雖然聲明時我們分別使用了String和Integer,但運行時關于泛型的信息被擦除了,我們無法區別strListClass和intListClass這兩個類型。這是因為,泛型信息只存在于代碼編譯階段,當程序運行到JVM上時,與泛型相關的信息會被擦除掉。類型擦除對于絕大多數應用系統開發者來說關系不太大,但是對于一些框架開發者來說,必須要注意。比如,Spark和Flink的開發者都使用了一些辦法來解決類型擦除問題,對于API調用者來說,受到的影響不大。

Scala中的泛型

對Java的泛型有了基本了解后,我們接著來了解一下Scala中的泛型。相比而言,Scala的類型系統更復雜,本文只介紹一些簡單語法,幫助讀者能夠讀懂一些源碼。

Scala中,泛型放在了中括號[]中。或者我們可以簡單地理解為,原來Java的泛型類,現在改為[T]即可。

我們創建一個Stack[T]的泛型類,并實現了兩個簡單的方法,類中各成員和方法都可以使用泛型T。我們也定義了泛型方法,形如isStackPeekEquals[T],方法中可以使用泛型T。

object MyStackDemo {  // Stack泛型類  class Stack[T] {   private var elements: List[T] = Nil   def push(x: T) { elements = x :: elements }   def peek: T = elements.head  }  // 泛型方法,檢查兩個Stack頂部是否相同  def isStackPeekEquals[T](p: Stack[T], q: Stack[T]): Boolean = {   p.peek == q.peek  }  def main(args: Array[String]): Unit = {    val stack = new Stack[Int]    stack.push(1)    stack.push(2)    println(stack.peek)    val stack2 = new Stack[Int]    stack2.push(2)    val stack3 = new Stack[Int]    stack3.push(3)    println(isStackPeekEquals(stack, stack2))    println(isStackPeekEquals(stack, stack3))  }}

“怎么理解Java/Scala泛型”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

温泉县| 武定县| 鹿泉市| 梅州市| 磐安县| 嘉兴市| 永仁县| 武城县| 墨玉县| 太康县| 麦盖提县| 利津县| 肃宁县| 玉林市| 绍兴县| 上饶县| 堆龙德庆县| 华宁县| 清水河县| 衡山县| 南郑县| 沙雅县| 五常市| 庆安县| 克东县| 肇东市| 汽车| 靖远县| 巍山| 施甸县| 金乡县| 洞口县| 广平县| 盐边县| 瓦房店市| 安岳县| 宝山区| 重庆市| 九台市| 监利县| 高要市|