摘要:在這種情況下,編譯器認(rèn)為調(diào)用泛型方法后,其返回值被賦給一個(gè)類(lèi)型的變量顯示地指明類(lèi)型參考資料編程的邏輯
一、泛型的概念
泛型實(shí)現(xiàn)了參數(shù)化類(lèi)型的概念,使代碼可以用于多種類(lèi)型
二、泛型的目的希望類(lèi)和方法能夠具備最廣泛的表達(dá)能力
用來(lái)指定容器要持有什么類(lèi)型的對(duì)象,而且由編譯器來(lái)保證類(lèi)型的正確性
三、泛型的使用
普通泛型類(lèi)
public class NormalGenericsClass{ private T key; public Generics(T key){ this.key = key; } public T getKey() { return key; } public void setKey(T key) { this.key = key; } } // 泛型類(lèi)實(shí)例 NormalGenericsClass a = new NormalGenericsClass (0); // Java7 開(kāi)始支持省略后面的參數(shù)類(lèi)型 NormalGenericsClass a = new NormalGenericsClass<>(0);
普通泛型接口
// Java中的 Comparator接口 public interface Comparator{ int compare(T o1, T o2); boolean equals(Object obj); } // 接口實(shí)現(xiàn)例子 java.text.Collator public abstract class Collator implements java.util.Comparator
普通泛型方法
privateint normalGenericsMethod(Generics i){ // 表示聲明 T為泛型,寫(xiě)在返回值類(lèi)型之前 // 也可以聲明多個(gè)泛型,如: return 0; } // 這是錯(cuò)誤的,會(huì)提示 Cannot resolve symbol "T" /*private int normalGenericsMethod(Generics i){ return 0; }*/
有上界的泛型:
上界:通過(guò)關(guān)鍵字extends來(lái)表示給定的上界,那么參數(shù)就必須是給定的上界或者其子類(lèi)型。上界可以是某個(gè)具體的類(lèi)或接口,也可以是其他參數(shù)
上界為具體的類(lèi)
public class GenericsUpperBoundextends NormalGenericsClass { public GenericsUpperBound(T key){ super(key); } }
上界為具體的接口
publicT compareWith(T[] arr){ T start = arr[0]; for(int i = 1; i < arr.length; i++){ System.out.print(start.equals(arr[i])); } return start; }
上界為其他類(lèi)型參數(shù)
public class OtherUpperBound四、通配符{ public void otherArgs(NormalGenericsClass a){ // E是OtherUpperBound的類(lèi)型參數(shù),T是otherArgs方法的類(lèi)型參數(shù) // T的上界限定為E } } //例子: OtherUpperBound a = new OtherUpperBound<>; OtherUpperBound b = new OtherUpperBound<>; a.otherArgs(b);
有限定通配符
//重寫(xiě)6中的方法 public void otherArgs(NormalGenericsClass extends E> a){ }
取自《Java編程的邏輯》8.2和 extends E>的區(qū)別
①:用于定義類(lèi)型參數(shù),它聲明了一個(gè)類(lèi)型參數(shù)T,可放在泛型類(lèi)定義中類(lèi)名后面、泛型方法返回值前面
② extends E>:用于實(shí)例化類(lèi)型參數(shù),它用于實(shí)例化泛型變量中的類(lèi)型參數(shù),只是這個(gè)類(lèi)型是未知的,只知道是E或E的某個(gè)子類(lèi)型
無(wú)限定通配符
public int demo(OtherUpperBound> a){ } // 這兩個(gè)等效 publicint demo(OtherUpperBound a){ }
通配符重要限制: 只能讀,不能寫(xiě)
取自《Java編程的邏輯》8.2
總結(jié):
1) 通配符形式都可以用類(lèi)型參數(shù)的形式來(lái)替代,通配符能做的,用類(lèi)型參數(shù)都能做
2) 通配符形式可以減少類(lèi)型參數(shù),形式上往往更為簡(jiǎn)單,可讀性也更好,所以,能用通配符的就用通配符
3) 如果類(lèi)型參數(shù)之間有依賴(lài)關(guān)系,或者返回值依賴(lài)類(lèi)型參數(shù),或者需要寫(xiě)操作,則只能用類(lèi)型參數(shù)
4) 通配符形式和類(lèi)型參數(shù)往往配合使用,定義必要的類(lèi)型參數(shù),使用通配符表達(dá)依賴(lài),并接受更廣泛的數(shù)據(jù)類(lèi)型
超類(lèi)型通配符(無(wú)法用類(lèi)型參數(shù)替代)
public int demo(OtherUpperBound super E> a){ }
取自《Java編程的邏輯》8.2五、泛型的局限性
總結(jié):
1)通配符的目的是為了使方法接口更為靈活,可以接受更為廣泛的類(lèi)型
2) super E>用于靈活寫(xiě)入或比較,使得對(duì)象可以寫(xiě)入父類(lèi)型的容器,使得父類(lèi)型的比較方法可以應(yīng)用于子類(lèi)對(duì)象,它不能被類(lèi)型參數(shù)形式替代
3)>和 extends E>用于靈活讀取,使得方法可以讀取E或E的任意子類(lèi)型的容器對(duì)象,它們可以用類(lèi)型參數(shù)的形式替代,但通配符形式更為簡(jiǎn)潔
父類(lèi)實(shí)現(xiàn)了一個(gè)泛型接口,子類(lèi)希望自定義泛型接口中的方法,只能重寫(xiě)父類(lèi)的實(shí)現(xiàn)
class Base implements Comparableclass Child extends Base // 希望重寫(xiě)Comparable的比較方法 /* class Child extends Base implements Comparable // 錯(cuò)誤,因?yàn)轭?lèi)型擦除的原因,實(shí)際實(shí)現(xiàn)的都是Comparable接口,接口不允許被實(shí)現(xiàn)兩次 */ // 正確重寫(xiě)Comparable的比較方法的方式 class Child extends Base { @Override public int compareTo(Base o){ if(!(o instanceof Child){ throw new IllegalArgumentException(); } Child c = (Child)o; 實(shí)現(xiàn)代碼 return 0; } 其他代碼 }
類(lèi)型參數(shù)不能作為靜態(tài)變量和靜態(tài)方法的類(lèi)型
Class Normal{ public static demo1(T param){ // 錯(cuò)誤的方法 } public static void demo2(E param){ // 正確的方法 } }
不能通過(guò)類(lèi)型參數(shù)創(chuàng)建對(duì)象
T a = new T(); // error Type parameter "T" cannot be instantiated directly六、泛型的使用細(xì)節(jié)
Java中的泛型是通過(guò)類(lèi)型擦除實(shí)現(xiàn)的,類(lèi)型參數(shù)在編譯時(shí)會(huì)被替換為Object
對(duì)于不同傳入的類(lèi)型實(shí)參,生成的相應(yīng)對(duì)象實(shí)例一樣
Genericsdemo = new Generics<>(123); Generics demo2 = new Generics<>("test"); System.out.println(demo.getClass() == demo2.getClass()); // true
靜態(tài)方法和泛型
靜態(tài)方法無(wú)法訪問(wèn)類(lèi)上定義的泛型;如果靜態(tài)方法操作的引用數(shù)據(jù)類(lèi)型不確定的時(shí)候,必須要將泛型定義在方法上。即:如果靜態(tài)方法要使用泛型的話,必須將靜態(tài)方法也定義成泛型方法
/** 如果在類(lèi)中定義使用泛型的靜態(tài)方法,需要添加額外的泛型聲明(將這個(gè)方法定義成泛型方法) 即使靜態(tài)方法要使用泛型類(lèi)中已經(jīng)聲明過(guò)的泛型也不可以。 如:public static void show(T t){..},此時(shí)編譯器會(huì)提示錯(cuò)誤信息 "StaticGenerator cannot be refrenced from static context" */ public staticvoid show(T t){ }
泛型的上下邊界添加,必須與泛型的聲明一起
//在泛型方法中添加上下邊界限制的時(shí)候,必須在權(quán)限聲明與返回值之間的上添加上下邊界, //即在泛型聲明的時(shí)候添加 //public T showKeyName(Generic container) 編譯器會(huì)報(bào)錯(cuò):"Unexpected bound" public T showKeyName(Generic container){ System.out.println("container key :" + container.getKey()); T test = container.getKey(); return test; }
基本類(lèi)型不能用于實(shí)例化類(lèi)型參數(shù)
泛型要求能包容的是對(duì)象類(lèi)型,基本類(lèi)型在java中不屬于對(duì)象
運(yùn)行時(shí)類(lèi)型查詢(xún)只適用于原始類(lèi)型
NormalGenericsClassa = new NormalGenericsClass<>(0); a instanceof NormalGenericsClass ; // Error Illegal generic type for instanceof a instanceof NormalGenericsClass ; // Error Cannot resolve symbol "T" a instanceof NormalGenericsClass; // Pass a instanceof NormalGenericsClass>; // Pass a.getClass(); // class com.example.demo.generics.NormalGenericsClass
類(lèi)型推斷只對(duì)賦值操作有效
Eg:
public class New{ public staticMap map(){ return new HashMap (); } } /** -- 方法中傳參 這時(shí)編譯器不會(huì)執(zhí)行類(lèi)型判斷。在這種情況下,編譯器認(rèn)為:調(diào)用泛型方法后, 其返回值被賦給一個(gè)Object類(lèi)型的變量 */ public class Test{ public static void main(String args[]){ fun(New.map()); } } public class Test{ public static void main(String args[]){ fun(New. 參考資料:
[1]《Java編程的邏輯》
[2]《Thinking in Java》
[3] https://blog.csdn.net/s10461/...
[4] https://www.cnblogs.com/lwbqq...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76461.html
摘要:方法即為收集器,它接收高階函數(shù)和的后端掘金年的第一天,我坐在獨(dú)墅湖邊,寫(xiě)下這篇文章。正因如此,所以最全系列教程后端掘金是從版本開(kāi)始引入的一個(gè)新的,可以替代標(biāo)準(zhǔn)的。 設(shè)計(jì)模式之單例模式 - 掘金前言 作為一個(gè)好學(xué)習(xí)的程序開(kāi)發(fā)者,應(yīng)該會(huì)去學(xué)習(xí)優(yōu)秀的開(kāi)源框架,當(dāng)然學(xué)習(xí)的過(guò)程中不免會(huì)去閱讀源碼,這也是一個(gè)優(yōu)秀程序員的必備素養(yǎng),在學(xué)習(xí)的過(guò)程中很多人會(huì)遇到的障礙,那就是設(shè)計(jì)模式。很多優(yōu)秀的框架會(huì)運(yùn)...
摘要:大多數(shù)待遇豐厚的開(kāi)發(fā)職位都要求開(kāi)發(fā)者精通多線程技術(shù)并且有豐富的程序開(kāi)發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問(wèn)題在面試中經(jīng)常會(huì)被提到。將對(duì)象編碼為字節(jié)流稱(chēng)之為序列化,反之將字節(jié)流重建成對(duì)象稱(chēng)之為反序列化。 JVM 內(nèi)存溢出實(shí)例 - 實(shí)戰(zhàn) JVM(二) 介紹 JVM 內(nèi)存溢出產(chǎn)生情況分析 Java - 注解詳解 詳細(xì)介紹 Java 注解的使用,有利于學(xué)習(xí)編譯時(shí)注解 Java 程序員快速上手 Kot...
摘要:但其實(shí),虛擬機(jī)并不支持這些語(yǔ)法糖。方式為每個(gè)泛型類(lèi)型創(chuàng)建唯一的字節(jié)碼表示,并且將該泛型類(lèi)型的實(shí)例都映射到這個(gè)唯一的字節(jié)碼表示上。GitHub 2.5k Star 的Java工程師成神之路 ,不來(lái)了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的不來(lái)了解一下嗎); GitHub 2.5k Star 的Java工程師成神之路 ,真的確定不來(lái)了解一下嗎); 本文從 ...
閱讀 1784·2021-10-27 14:15
閱讀 3864·2021-10-08 10:12
閱讀 1178·2021-09-22 15:55
閱讀 3239·2021-09-22 15:17
閱讀 844·2021-09-02 15:40
閱讀 1757·2019-08-29 18:33
閱讀 1106·2019-08-29 15:22
閱讀 2361·2019-08-29 11:08