中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

做網(wǎng)站優(yōu)化選阿里巴巴還是百度今日頭條10大新聞

做網(wǎng)站優(yōu)化選阿里巴巴還是百度,今日頭條10大新聞,阿里云oss可以做網(wǎng)站,濰坊地區(qū)做幼兒園網(wǎng)站的作為一個(gè) Java 程序員&#xff0c;用到泛型最多的&#xff0c;我估計(jì)應(yīng)該就是這一行代碼&#xff1a; List<String> list new ArrayList<>();這也是所有 Java 程序員的泛型之路開始的地方啊。 不過本文講泛型&#xff0c;先不從這里開始講&#xff0c;而是再往前…

作為一個(gè) Java 程序員,用到泛型最多的,我估計(jì)應(yīng)該就是這一行代碼:

List<String> list = new ArrayList<>();

這也是所有 Java 程序員的泛型之路開始的地方啊。

不過本文講泛型,先不從這里開始講,而是再往前看一下,看一看沒有泛型的時(shí)候,Java 代碼是怎么寫的,然后我們才會(huì)知道為什么要加入泛型,泛型代碼該怎么寫。

這里插播一下我的微信公眾號(hào),希望大家能夠多多關(guān)注,我會(huì)不定期更新優(yōu)秀的技術(shù)文章:

接下來,開始我們的正文。

為什么要設(shè)計(jì)泛型

提高代碼重用性

沒有泛型之前,我們寫一個(gè)兩數(shù)相加的函數(shù):

public static int add(int a, int b) {return a + b;
}

看似沒問題,對(duì)吧。不過這個(gè)時(shí)候我們想計(jì)算 float 類型的加法,那這個(gè)函數(shù)就不行了,因?yàn)樗荒苡?jì)算 int 值。此時(shí)就只能再加入一個(gè)相同的函數(shù)了:

public static float add(float a, float b) {return a + b;
}

現(xiàn)在我們有兩個(gè)方法能夠計(jì)算 int 和 float 類型的加法。那現(xiàn)在如果要計(jì)算 String 類型的加法呢,這兩個(gè)方法就又不夠用了。面對(duì)這樣的需求,在沒有泛型的支持下,我們只能不斷地增加邏輯基本相同的方法,代碼重用性極低。
這就是泛型要解決的第一個(gè)問題:提高代碼重用性。
那在泛型的加持下,我們?nèi)绾尉帉戇@個(gè)函數(shù)呢?

public static <T extends Number> double add(T a, T b) {return a.doubleValue() + b.doubleValue();
}

這個(gè)方法使用了泛型,它能夠處理任何類型的數(shù)字相加,不需要針對(duì)每個(gè)類型編寫各自的加法方法。這就大大提高了代碼的重用性,有了這個(gè)方法,那些固定類型的方法就都可以刪了。
特別是一些邏輯相同的代碼,使用泛型不僅能夠提高代碼重用性,還能夠提高可讀性。比如說下面這段代碼,真是的是非常好用:

public static <T> void printArray(T[] array) {for (T element : array) {System.out.println(element);}
}

泛型的這個(gè)特性雖然很牛了,但是這還不是 Java 要設(shè)計(jì)泛型的全部原因。因?yàn)榉盒瓦€有一個(gè)作用,那就是保證類型安全。

保證類型安全

在說泛型的這個(gè)作用之前,先問大家一個(gè)問題,咱們常用的集合 ArrayList 是 Java 哪個(gè)版本加入的呢?泛型又是 Java 哪個(gè)版本加入的呢?

答案:ArrayList 是 Java 1.2 版本加入的,而泛型是 Java 1.5 加入的。

也就是說,有一段時(shí)時(shí)間,ArrayList 不是大家普遍認(rèn)識(shí)的帶泛型的 ArrayList<T> 這種形式,而是一個(gè)只能存放 Object 的列表。

在那一段泛型之光沒有照耀到 Java 的日子里,保證類型安全成為了 Java 程序員在使用集合時(shí)不得不考慮的事情,考慮下面這一段代碼:

ArrayList list = new ArrayList();
list.add("123");
// do some work......
Integer num = (Integer) list.get(0);

這段代碼沒有使用泛型來使用 ArrayList,我們加入了字符串 "123",但是在使用時(shí),我們假定程序員忘記了加入的類型,他只記得好像應(yīng)該是數(shù)字,于是在獲取時(shí)就直接使用了 Integer 類強(qiáng)轉(zhuǎn)。

這樣的代碼是能通過編譯的,但是在運(yùn)行的時(shí)候,會(huì)崩潰:

 Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

這是一個(gè)典型的未使用泛型,而導(dǎo)致的類型安全無法保證,引發(fā)的崩潰。讓程序員去保證類型安全,本身是不靠譜的做法,特別是在這種都是 Object 對(duì)象的列表中,鬼都不會(huì)知道存著的是個(gè)什么鬼。

這個(gè)時(shí)候就需要泛型出場(chǎng)了,泛型能夠在編譯時(shí)保證類型安全。例如上面的代碼,我們加入泛型:

ArrayList<String> list = new ArrayList<>();
list.add("123");
Integer num = (Integer) list.get(0);

首先,ArrayList 加入泛型后,我們就知道這個(gè)列表是只能存入 String 類型的,也就不會(huì)將其轉(zhuǎn)換為 Integer。那如果我非要轉(zhuǎn)換呢,javac 編譯器就會(huì)報(bào)錯(cuò):

錯(cuò)誤: 不兼容的類型: String無法轉(zhuǎn)換為IntegerInteger num = (Integer) list.get(0);

這樣類型安全就可以在編譯時(shí)得到保證,不會(huì)出現(xiàn)在運(yùn)行時(shí)的崩潰。

例子的代碼很簡(jiǎn)單,大家可能看不到這一點(diǎn)對(duì)于軟件開發(fā)有多重要,在大型復(fù)雜的項(xiàng)目中,這種類型安全的保證,是能減少很多運(yùn)行時(shí)的崩潰的。特別是,一般像這種類型不一致的崩潰很多都是偶現(xiàn)的,偶現(xiàn)的 BUG 是最惡心的,因此使用泛型保證類型安全是十分必要的。

消除強(qiáng)制類型轉(zhuǎn)換

泛型的這個(gè)作用其實(shí)就是上面保證類型安全這一點(diǎn)帶來的。沒有用泛型時(shí),需要我們使用強(qiáng)制類型轉(zhuǎn)化,但是加入泛型后,編譯器已經(jīng)能夠知道我們存入的是什么類型,因此也就不需要我們進(jìn)行強(qiáng)制類型轉(zhuǎn)換了。

既然泛型有那么大的作用,那我們就趕緊把泛型用起來吧。

使用泛型

這一節(jié),我們來看看如何使用系統(tǒng)提供的泛型類,以及其中需要注意的事項(xiàng)。

最常用到泛型的地方便是集合了,使用這些泛型集合類時(shí),只需要把具體泛型參數(shù) <T> 替換為需要的類型即可,例如 ArrayList<String>、ArrayList<Number>、 Map<String, Integer> 等。

如果在使用泛型類時(shí)不指定類型參數(shù),編譯器會(huì)給出警告,且只能將 <T> 視為 Object 類型。這個(gè)時(shí)候就需要程序員自己去保證類型安全了,因此強(qiáng)烈不建議這么做,因?yàn)檫@樣容易將類型轉(zhuǎn)換異常帶到運(yùn)行時(shí)中去。

使用泛型基本就需要注意以上兩點(diǎn),下面介紹一下在使用泛型時(shí)的注意事項(xiàng),這也是大家很少關(guān)注到的向上轉(zhuǎn)型的問題。

在 Java 中,ArrayList<T> 是實(shí)現(xiàn)了 List<T> 接口,也就是說它可以向上轉(zhuǎn)型為 List<T>

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable

那么問題就來了,當(dāng)泛型參數(shù)不同時(shí),還能向上轉(zhuǎn)型么,說具體一點(diǎn),ArrayList<String> 能轉(zhuǎn)型為 List<Number> 么?

答案是不行的:

ArrayList List = new ArrayList<String>();    //Raw use of parameterized class 'ArrayList'
List<Integer> list = new ArrayList<String>();    //直接報(bào)錯(cuò)

為什么 Java 不允許這么轉(zhuǎn)型呢?因?yàn)檫\(yùn)行轉(zhuǎn)型的話,那么對(duì)于一個(gè) ArrayList<String> 的容器,我將其轉(zhuǎn)型為 ArrayList<Integer> 就可以往里面加入 Integer 對(duì)象了,這明顯會(huì)造成 ClassCastException。泛型的存在用于限定類型的,這么一搞,泛型就失去了其作用。

這里,大家可以簡(jiǎn)單理解為,當(dāng)泛型參數(shù)不一樣時(shí),兩個(gè)類就沒有太大關(guān)系了。例如 ArrayList<Integer>List<Number> 兩者完全沒有繼承關(guān)系。

編寫泛型

知道怎么使用系統(tǒng)的泛型之后,我們現(xiàn)在就來看看如何編寫自己的泛型類。

泛型作為對(duì)類型進(jìn)行限制的一種方式,我們編寫泛型代碼,也就是對(duì)使用我們代碼的人進(jìn)行一種限制。在這種情況下,我們是作為其他程序員的底層,向上提供某種框架代碼,讓其他程序員能夠在我們?cè)O(shè)定的框架中更容易地編寫代碼實(shí)現(xiàn)功能。這有點(diǎn)類似于庫(kù)的開發(fā)者,或是框架開發(fā)者,作為這種角色,寫好泛型代碼就更顯得尤為重要了。畢竟,你也不想讓別人說,這代碼寫得就跟一坨屎一樣吧。

編寫泛型類

編寫泛型類,是比普通類要復(fù)雜的。這里我們就用 Pair<F, S> 這個(gè)類作為目標(biāo),一步一步編寫出一個(gè)合格的泛型類。Pair 類是 Android 開發(fā)中一個(gè)簡(jiǎn)單的使用工具類,用于存儲(chǔ)一對(duì)相關(guān)聯(lián)的對(duì)象。

我們的第一版 Pair 只能使用沒有使用泛型:

public class Pair {public final String first;public final String second;
}

那這肯定是不行的,因?yàn)檫@個(gè) Pair 只能存放 String 類型的 first 和 second,那了能夠存放所有類型,我們就使用泛型 <T>

public class Pair<T> {public final T first;public final T second;
}

我們把 firstsecondT 來修飾,表示其這兩個(gè)成員變量是 T 類型的。而這個(gè) T 類型,Java 是不知道的,我們必須聲明告訴 Java 這是一個(gè)類型,因此類名從 Pair 變成了 Pair<T>,后面的 <T> 就是我們的泛型類型聲明。

上面的代碼看上去沒問題,但是這個(gè) Pair<T> 只能存放的 firstsecond 必須是相同的類型 T,那不同類型的怎么辦呢?這時(shí)候我們?cè)偌右粋€(gè)泛型不就行了:

public class Pair<F, S> {public final F first;public final S second;
}

在加入兩個(gè)泛型之后,firstsecond 的類型對(duì)應(yīng)不同的泛型,這樣就可以表示不同的類型了,注意 F、S 這兩個(gè)不同的泛型都需要在類上進(jìn)行聲明。

我們?cè)跒?Pair<F, S> 添加個(gè)構(gòu)造方法:

public class Pair<F, S> {public final F first;public final S second;public Pair(F first, S second) {this.first = first;this.second = second;}
}

這算是一個(gè)簡(jiǎn)單的泛型類,那接下來,我們?cè)贋樗帉懸粋€(gè)泛型方法。

編寫泛型方法

此處的泛型方法是指靜態(tài)方法,而不是成員方法。這兩種方法在使用泛型時(shí)是有一些區(qū)別的,其中最重要的一點(diǎn)就是,靜態(tài)方法是不能使用類上聲明的泛型類型,必須得自己聲明泛型類型。例如,下面的代碼將編譯錯(cuò)誤:

public static class Pair<F, S> {public final F first;public final S second;//編譯錯(cuò)誤,F、S 類型不能在 static 方法上使用public static Pair<F, S> create(F a, S b) {return new Pair<F, S>(a, b);}
}

可以想一想,為什么靜態(tài)方法不能使用類上已經(jīng)聲明的泛型類型呢?

在回答這個(gè)問題之前,我們可以先想一下,類上的泛型類型,是在什么時(shí)候確定下來的呢?是在類創(chuàng)建的時(shí)候,我們?cè)?new 的時(shí)候是需要提供具體類型的,這個(gè)時(shí)候泛型就被具體化為某個(gè)特定類型。不同的對(duì)象可能被創(chuàng)建為不同的類型,而靜態(tài)方法只跟類相關(guān),跟具體對(duì)象無關(guān),而這些泛型又是跟具體對(duì)象相關(guān)的。所以靜態(tài)對(duì)象不能使用類上聲明的泛型也就變得合理了。

那要想使靜態(tài)方法使用泛型,那就必須這個(gè)靜態(tài)方法自己聲明泛型:

public static <F, S> Pair <F, S> create(F a, S b) {return new Pair<F, S>(a, b);
}

這個(gè)靜態(tài)方法在函數(shù)名前使用 <F, S> 來聲明了兩個(gè)泛型,那么后續(xù)這兩個(gè)泛型就可以在這個(gè)函數(shù)中使用了。此時(shí)注意,這里的 FS 雖然與 Pair 上的 F、S 泛型看似相同,實(shí)際上是沒有任何關(guān)系的。所以為了避免產(chǎn)生誤會(huì),一般都會(huì)使用不同的泛型名,例如將這個(gè)方法的 <F, S> 變成 <A, B>

public static class Pair<F, S> {public final F first;public final S second;public static <A, B> Pair <A, B> create(A a, B b) {return new Pair<A, B>(a, b);}
}

這樣才能夠清楚地將靜態(tài)方法的泛型類型和實(shí)例類型的泛型類型區(qū)分開。

在使用時(shí),我們可以使用如下代碼創(chuàng)建一個(gè) Pair<F, S> 實(shí)例:

Pair<String, Integer> pair = Pair.create("123", 123);

這里總結(jié)一下編寫泛型需要注意的幾點(diǎn):

  • 編寫泛型時(shí),需要定義泛型類型 <T>
  • 靜態(tài)方法不能引用類上的泛型類型 <T>,必須定義自己方法特有的泛型類型;
  • 泛型可以同時(shí)定義多個(gè),例如 <F, S><F、S、T>

在這里我們需要注意泛型的一個(gè)限制,那就是不能使用泛型類型直接創(chuàng)建對(duì)象。這一點(diǎn)也好理解,T 是什么類型只有在使用時(shí),指定了泛型的具體類型才能確定。T 類型是一個(gè)抽象的類型,它是無法直接 new 出來的,就像你無法直接 new 一個(gè) interface 一樣。例如下面的代碼是錯(cuò)誤的:

public static class Pair<F, S> {public final F first;public final S second;public Pair(F first, S second) {this.first = new F();        //錯(cuò)誤this.second = new S();       //錯(cuò)誤}
}

這里使用 F 類型的默認(rèn)構(gòu)造,設(shè)想一下假如這個(gè)類型被確定為一個(gè)沒有默認(rèn)構(gòu)造方法的類型呢。所以使用泛型類型創(chuàng)建對(duì)象是不行的。

Java 的泛型實(shí)現(xiàn)方式:類型擦除

上面的幾節(jié)介紹了泛型的好處,泛型的使用,那這一節(jié)我們就來看看 Java 是如何實(shí)現(xiàn)泛型技術(shù)的。

首先,泛型編程并非 Java 特有的,在其他語言 C++、C# 上都有類似的技術(shù),只不過名稱不同而已,例如 C++ 上叫模版。在這些技術(shù)的加持下,程序員可以編寫與具體類型無關(guān)的代碼,只需要在使用時(shí)指定具體類型,從而提高代碼的復(fù)用性;并且在編譯時(shí)進(jìn)行類型檢查,減少運(yùn)行時(shí)錯(cuò)誤。

Java 的泛型是通過類型擦除(Type Erasure)來實(shí)現(xiàn)的。也就是說在編譯時(shí)將泛型類型擦除,替換為其上限類型(通常為 Object),并在必要時(shí)插入類型轉(zhuǎn)換。這種機(jī)制在編譯時(shí)處理泛型類型,而在運(yùn)行時(shí)移除了所有的泛型信息,因此叫做類型擦除。

這也就意味著,Java 的泛型是由編譯器實(shí)現(xiàn)的,在編譯成 class 文件時(shí)類型信息已經(jīng)被擦除了,因此運(yùn)行時(shí),Java 虛擬機(jī)是沒有任何泛型信息的。

例如上面我們編寫的 Pair 的這個(gè)類,在我們看來,它是這樣的,在源代碼階段,里面是包含泛型信息的:

public static class Pair<F, S> {public final F first;public final S second;public Pair(F first, S second) {this.first = first;this.second = second;}public static <A, B> Pair<A, B> create(A a, B b) {return new Pair<A, B>(a, b);}
}

那么在虛擬機(jī)的視角,它是這樣的:

public class Pair {private Object first;private Object last;public Pair(Object first, Object last) {this.first = first;this.last = last;}
}

從這里就能看到,這個(gè) Pair 在運(yùn)行時(shí)已經(jīng)沒有泛型信息了,所有的泛型類型都被替換為了 Object

那么既然我們定義的泛型類型最終都變成了 Object,那我們就知道了 Java 泛型的一個(gè)局限:泛型類型 <T> 不能是基本類型。
因?yàn)橄?intfloat 這些基本類型不是 Object 的子類,所以我們必須使用包裝類:

Pair<float, int> pair = Pair.create(3.15, 123);    //編譯錯(cuò)誤
Pair<Float, Integer> pair = Pair.create(3.15F, 123);    //編譯通過

盡管 Java 的泛型在編譯時(shí)通過類型擦除機(jī)制移除了泛型類型信息,但 Java 編譯器會(huì)在 class 文件中保留一些泛型信息,以便工具和開發(fā)人員能夠利用這些信息進(jìn)行反射和調(diào)試。所以如果大家把這個(gè)類編譯為 class 文件之后,再查看它的反編譯的內(nèi)容,會(huì)發(fā)現(xiàn)它是有一些泛型信息的。但這并不意味著 JVM 在運(yùn)行時(shí)會(huì)攜帶這些類型信息,既然是類型擦除,也就是說泛型類型參數(shù)被擦除并替換為其邊界類型,如果沒有指定邊界,則默認(rèn)為 Object。

這里又引入了邊界類型這個(gè)概念,在下一篇文章中,我們就來詳細(xì)聊聊這個(gè)邊界類型,這也是泛型中比較重要和難的點(diǎn)。

http://www.risenshineclean.com/news/56529.html

相關(guān)文章:

  • 傳奇輔助網(wǎng)站怎么做廣告關(guān)鍵詞有哪些類型
  • 南寧微網(wǎng)站制作搜索引擎營(yíng)銷特點(diǎn)是什么
  • 醫(yī)療不可以做網(wǎng)站圖片外鏈工具
  • 河北網(wǎng)站制作多少錢怎么在網(wǎng)上推廣廣告
  • 三站一體網(wǎng)站公司1688網(wǎng)站
  • 如何優(yōu)化網(wǎng)站圖片大小品牌營(yíng)銷策劃網(wǎng)站
  • 網(wǎng)站欄目頁面百度快速提交入口
  • 網(wǎng)站建設(shè)費(fèi)用如何做賬務(wù)處理baidu com百度一下
  • 做電影網(wǎng)站要怎么樣的主機(jī)bt磁力種子搜索引擎
  • 做企業(yè)云網(wǎng)站的企業(yè)郵箱一個(gè)新品牌怎樣營(yíng)銷推廣
  • 企業(yè)員工管理信息系統(tǒng)上海企業(yè)優(yōu)化
  • 外貿(mào)建網(wǎng)站免費(fèi)模板東莞搜索seo網(wǎng)站關(guān)鍵詞優(yōu)化
  • 電子商務(wù)網(wǎng)站開發(fā)教案nba實(shí)力榜最新排名
  • 杭州網(wǎng)站設(shè)計(jì)渠道百度網(wǎng)盤怎么找片
  • 如何做企業(yè)網(wǎng)站方法seo還有用嗎
  • 做seo要明白網(wǎng)站內(nèi)知識(shí)搜索引擎
  • 可以生成靜態(tài)網(wǎng)站源碼汕頭seo推廣
  • 有什么正規(guī)的網(wǎng)站做代加工百度問答庫(kù)
  • 東莞市營(yíng)銷網(wǎng)站建設(shè)單頁關(guān)鍵詞優(yōu)化費(fèi)用
  • 廣東品牌網(wǎng)站建設(shè)平臺(tái)深圳關(guān)鍵詞優(yōu)化平臺(tái)
  • 關(guān)鍵詞做網(wǎng)站標(biāo)題是什么意思網(wǎng)址導(dǎo)航大全
  • 現(xiàn)在的網(wǎng)站設(shè)計(jì)山東濟(jì)南seo整站優(yōu)化公司
  • 無憂網(wǎng)站源碼國(guó)外seo工具
  • 商城網(wǎng)站做推廣有什么好處seo名詞解釋
  • dreamweaver做網(wǎng)站學(xué)習(xí)解析seo站內(nèi)優(yōu)化包括
  • 襄陽教育云平臺(tái)網(wǎng)站建設(shè)2022世界足球排行榜
  • 網(wǎng)站關(guān)鍵詞快速排名軟件網(wǎng)絡(luò)運(yùn)營(yíng)師
  • 怎么做自己的彩票網(wǎng)站現(xiàn)在有哪些網(wǎng)址
  • 網(wǎng)站空間免費(fèi) 優(yōu)幫云站長(zhǎng)工具seo綜合查詢?cè)趺搓P(guān)閉
  • python做網(wǎng)站入門武漢網(wǎng)站制作推廣