自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java/Scala 泛型快速入門教程

開發(fā) 后端
本文簡單介紹了Java/Scala的泛型,它允許數(shù)據(jù)類型是可變,提升了代碼的復(fù)用性,是很多框架都會(huì)采用的技術(shù),開發(fā)者非常有必要了解泛型的基本用法。

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

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

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

[[315685]]

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

Java泛型類

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

  1. 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());    }} 

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

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

Java泛型接口類

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

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

繼承并實(shí)現(xiàn)這個(gè)接口類的代碼如下:

  1. 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泛型方法

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

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

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

通配符

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

泛型小結(jié)

對(duì)Java的泛型總結(jié)下來發(fā)現(xiàn),雖然它的語法有時(shí)候讓人有些眼花繚亂,其本質(zhì)是為了接受不同的數(shù)據(jù)類型,增強(qiáng)代碼的復(fù)用性。

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

  • T 代表一般的任何類。
  • E 代表元素(Element)或異常(Exception)。
  • K 代表鍵(Key)。
  • V 代表值(Value),通常與K一起配合使用,比如

Java的泛型給開發(fā)者提供了不少便利,尤其是保證了底層代碼簡潔性,因?yàn)檫@些底層代碼通常被封裝為一個(gè)框架,會(huì)有各種各樣的上層應(yīng)用調(diào)用這些底層代碼進(jìn)行特定的業(yè)務(wù)處理,每次調(diào)用都可能涉及泛型問題。比如,大數(shù)據(jù)框架Spark和Flink中都需要開發(fā)者基于泛型進(jìn)行數(shù)據(jù)處理。

以上只對(duì)泛型做了一個(gè)簡單的介紹,實(shí)際上在具體使用時(shí)還有一些細(xì)節(jié)需要注意。

類型擦除

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

  1. 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)); 

雖然聲明時(shí)我們分別使用了String和Integer,但運(yùn)行時(shí)關(guān)于泛型的信息被擦除了,我們無法區(qū)別strListClass和intListClass這兩個(gè)類型。這是因?yàn)?,泛型信息只存在于代碼編譯階段,當(dāng)程序運(yùn)行到JVM上時(shí),與泛型相關(guān)的信息會(huì)被擦除掉。類型擦除對(duì)于絕大多數(shù)應(yīng)用系統(tǒng)開發(fā)者來說關(guān)系不太大,但是對(duì)于一些框架開發(fā)者來說,必須要注意。比如,Spark和Flink的開發(fā)者都使用了一些辦法來解決類型擦除問題,對(duì)于API調(diào)用者來說,受到的影響不大。

Scala中的泛型

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

Scala中,泛型放在了中括號(hào)[]中?;蛘呶覀兛梢院唵蔚乩斫鉃椋瓉鞪ava的泛型類,現(xiàn)在改為[T]即可。

我們創(chuàng)建一個(gè)Stack[T]的泛型類,并實(shí)現(xiàn)了兩個(gè)簡單的方法,類中各成員和方法都可以使用泛型T。我們也定義了泛型方法,形如isStackPeekEquals[T],方法中可以使用泛型T。

  1. object MyStackDemo {  // Stack泛型類  class Stack[T] {   private var elements: List[T] = Nil   def push(x: T) { elements = x :: elements }   def peek: T = elements.head  }  // 泛型方法,檢查兩個(gè)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))  }} 

總結(jié)

本文簡單介紹了Java/Scala的泛型,它允許數(shù)據(jù)類型是可變,提升了代碼的復(fù)用性,是很多框架都會(huì)采用的技術(shù),開發(fā)者非常有必要了解泛型的基本用法。

責(zé)任編輯:趙寧寧 來源: 今日頭條
相關(guān)推薦

2010-05-21 12:50:45

Subversion快

2010-05-27 17:27:45

Subversion快

2009-09-25 10:24:40

Androind入門教OPhone

2016-12-02 19:19:35

大數(shù)據(jù)Hadoop

2009-07-08 15:12:48

Java Servle

2011-06-03 08:49:54

Java

2014-06-04 10:42:34

Swift蘋果iOS

2009-09-09 14:11:58

Scala泛型

2021-06-17 06:51:32

Java泛型Java編程

2015-07-23 10:54:09

Java Mybati框架

2010-08-03 13:06:15

Flex Builde

2013-08-29 14:12:52

Storm分布式實(shí)時(shí)計(jì)算

2022-03-22 11:35:10

數(shù)據(jù)建模PostgreSQLCitus

2014-05-26 15:35:55

Web組件Web Compone

2010-05-31 10:56:51

SVN服務(wù)器架設(shè)

2014-07-23 09:48:51

GitHub設(shè)計(jì)師

2011-07-21 10:29:18

iPhone 開發(fā)

2010-07-27 15:53:15

2010-08-03 14:37:30

Flex入門教程

2010-06-13 09:45:35

Widget開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)