新聞中心
泛型(Generics)是強類型編程語言中經常使用的一種技術。很多框架的代碼中都會大量使用到泛型,比如在Java中我們經??吹降模?/p>

在威寧等地區(qū),都構建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網站制作、網站設計、外貿網站建設 網站設計制作定制網站,公司網站建設,企業(yè)網站建設,品牌網站設計,營銷型網站,成都外貿網站制作,威寧網站建設費用合理。
- List
strList = new ArrayList ();List doubleList = new LinkedList ();
在這段代碼中,ArrayList就是一個泛型類,List就是一個泛型接口類,他們提供給開發(fā)者一個放置不同類型的集合容器,我們可以向這個集合容器中添加String、Double以及其他各類數(shù)據(jù)類型。無論內部存儲的是什么類型,集合容器提供給開發(fā)者的功能都是相同的,比如添加add,get等。有了泛型,我們就沒必要創(chuàng)建StringArrayList、DoubleArrayList等集合了,否則代碼量太大,維護起來成本極高。
在Java中,泛型一般有三種使用方式:泛型類,泛型方法和泛型接口類。一般使用尖括號<>來接收泛型參數(shù)。
Java泛型類
假如我們自己定義一個支持泛型的MyArrayList,這個列表類可以簡單支持初始化和數(shù)據(jù)寫入。只要在類名后面加上 就可以讓這個類支持泛型,類內部的一些屬性和方法都可以使用泛型類型T。當然我們給這個類也可以添加多個泛型參數(shù),比如
- public class MyArrayList
{ 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 strList = new MyArrayList (2); strList.set("first", 0); strList.set("second", 1); System.out.println(strList.toString()); }}
我們也可以從父類中繼承并擴展泛型,比如Flink源碼中有這樣一個類定義,子類繼承了父類的T,同時自己增加了泛型KEY:
- public class KeyedStream
extends DataStream { ...}
Java泛型接口類
Java泛型接口類的定義和Java泛型類基本相同。下面的代碼展示了List接口中定義subList方法,該方法截取原來列表的一部分。
- public interface List
{ ... public List subList(int fromIndex, int toIndex);}
繼承并實現(xiàn)這個接口類的代碼如下:
- public class ArrayList
implements List { ... public List subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); }}
Java泛型方法
泛型方法可以存在于泛型類(包括接口類)中,也可以存在于普通的類中。
- public class MyArrayList
{ ... // public關鍵字和返回值E之間的 表明這是一個泛型方法 // 泛型方法中的類型E和泛型類中的類型T可以不一樣 public E processElement(E element) { ... return E; }}
從上面的代碼示例可以看出,public或private關鍵字和方法返回值之間的尖括號 表示這是一個泛型方法。泛型方法的類型E和泛型類中的T可以不一樣,或者說,如果泛型方法是泛型類的一個成員,泛型方法既可以繼續(xù)使用類中的T,也可以自己定義新的類型E。
通配符
除了用 表示泛型外,還有 這種形式。 被稱為通配符,用來適應各種不同的泛型。
泛型小結
對Java的泛型總結下來發(fā)現(xiàn),雖然它的語法有時候讓人有些眼花繚亂,其本質是為了接受不同的數(shù)據(jù)類型,增強代碼的復用性。
我們可以在一個類里使用多個泛型,每個泛型一般使用大寫字母表示。Java為此提供了一些大寫字母使用規(guī)范:
- T 代表一般的任何類。
- E 代表元素(Element)或異常(Exception)。
- K 代表鍵(Key)。
- V 代表值(Value),通常與K一起配合使用,比如
Java的泛型給開發(fā)者提供了不少便利,尤其是保證了底層代碼簡潔性,因為這些底層代碼通常被封裝為一個框架,會有各種各樣的上層應用調用這些底層代碼進行特定的業(yè)務處理,每次調用都可能涉及泛型問題。比如,大數(shù)據(jù)框架Spark和Flink中都需要開發(fā)者基于泛型進行數(shù)據(jù)處理。
以上只對泛型做了一個簡單的介紹,實際上在具體使用時還有一些細節(jié)需要注意。
類型擦除
Java的泛型有一個遺留問題,那就是類型擦除(Type Erasure)。我們先看一下下面的代碼:
- Class> strListClass = new ArrayList
().getClass();Class> intListClass = new ArrayList ().getClass();// 輸出:class java.util.ArrayListSystem.out.println(strListClass);// 輸出:class java.util.ArrayListSystem.out.println(intListClass);// 輸出:trueSystem.out.println(strListClass.equals(intListClass));
雖然聲明時我們分別使用了String和Integer,但運行時關于泛型的信息被擦除了,我們無法區(qū)別strListClass和intListClass這兩個類型。這是因為,泛型信息只存在于代碼編譯階段,當程序運行到JVM上時,與泛型相關的信息會被擦除掉。類型擦除對于絕大多數(shù)應用系統(tǒng)開發(fā)者來說關系不太大,但是對于一些框架開發(fā)者來說,必須要注意。比如,Spark和Flink的開發(fā)者都使用了一些辦法來解決類型擦除問題,對于API調用者來說,受到的影響不大。
Scala中的泛型
對Java的泛型有了基本了解后,我們接著來了解一下Scala中的泛型。相比而言,Scala的類型系統(tǒng)更復雜,本文只介紹一些簡單語法,幫助讀者能夠讀懂一些源碼。
Scala中,泛型放在了中括號[]中。或者我們可以簡單地理解為,原來Java的泛型類 ,現(xiàn)在改為[T]即可。
我們創(chuàng)建一個Stack[T]的泛型類,并實現(xiàn)了兩個簡單的方法,類中各成員和方法都可以使用泛型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的泛型,它允許數(shù)據(jù)類型是可變,提升了代碼的復用性,是很多框架都會采用的技術,開發(fā)者非常有必要了解泛型的基本用法。
分享文章:Java/Scala泛型快速入門教程
鏈接地址:http://m.fisionsoft.com.cn/article/dpddocs.html


咨詢
建站咨詢
