java泛型、泛型類及特點、限制泛型、類型通配符聲明、泛型方法

java泛型:

  • 泛型簡介
  • 泛型類
  • 限制泛型可用類型
  • 類型通配聲明
  • 泛型方法

問題: 如果我們需要產生多個對象,每個對象的邏輯完全一樣,只是對象內的成員變量的類型不同。那我們該如何去做?如果按照正常的做法就要創建多個類文件,給每個類中的成員變量設置指定的數據類型。這樣做的缺點: 這樣會導致類膨脹,重用太差。解決方法: 創建一個類文件,給這個類中2成員變量設置Object(是所有類的父類)數據類型。 缺點: 編譯的時候正常,但運行的時候可能會出現異常。因為Object導致整個類對變量的屬性很模糊。面對這樣的問題在JDK1.5以后引入泛型

class Cla1
{Object a;public Cla1(Object a) {this.a=a;}public Object getData(){return a;}
}
//class cla2
//{
//	String a;
//	public cla2(String a) {
//		this.a=a;
//	}
//	public String getData(){
//		return a;
//	}
//}
public class Mian {public static void main(String[] args) {Cla1 c1=new Cla1("String");System.out.println(c1.getData());//System.out.println((Integer)c1.getData());Object導致整個類對變量的屬性很模糊,在強制類型轉換的時候會出現下列錯誤//Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer//at Mian.main(Mian.java:25)}
}

泛型簡介:

  • 泛型可以在編譯的時候檢查類型安全,并且所有的強制轉換都是自動的和隱式的。
  • 泛型的原理就是 類型的參數化,即把類型看做參數。也就是說把所有要操作的數據類型看做參數,就像方法的形式參數是運行時傳遞的值的占位符一樣。
  • 簡單的說,類型變量 扮演的角色就如同一個參數,它是提供給編譯器用來類型檢查的信息。
  • 泛型可以提高代碼的擴展性和重用性。
class Cla1<T>//T必須是引用類型
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}
}
public class Mian {public static void main(String[] args) {Cla1<Integer> c1=new Cla1<Integer>(10);//<Integer>明確類中參數的類型,相當于類型的參數化,用<>表示//Cla1<int> c1=new Cla1<int>(10);這樣寫會報錯,<>括號內的必須是引用類型,System.out.println(c1.getData());}
}

泛型類及特點:

  • 泛型的類型參數可以是泛型類
  • 泛型類可以同時設置多個類型參數
  • 泛型類可以繼承泛型類
  • 泛型類可以實現泛型接口

泛型類可以同時設置多個類型參數

class Cla1<T> //一個類型參數
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}
}
class Cla2<T1,T2> //多個類型參數
{T1 a;T2 b;public Cla2(T1 a,T2 b) {this.a=a;this.b=b;}public T1 getDataA(){return a;}public T2 getDataB(){return b;}
}
public class Mian {public static void main(String[] args) {Cla1<Integer> c1=new Cla1<Integer>(10);System.out.println(c1.getData());Cla2<Integer,String> c2=new Cla2<Integer,String>(30,"輸出");System.out.println(c2.getDataA());System.out.println(c2.getDataB());System.out.println(c2.getDataA()+c2.getDataB());//數字和字符串相加,+起連接作用Cla2<Integer,Integer> c3=new Cla2<Integer,Integer>(100,120);System.out.println(c3.getDataA());System.out.println(c3.getDataB());System.out.println(c3.getDataA()+c3.getDataB());//數字和數字相加,+就是數值相加											    //有的博客說這里的數值不能直接相加		}
}

泛型類型可以是泛型類:

class Cla1<T> //一個類型參數
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}
}
public class Main {public static void main(String[] args) {Cla1<Cla1<Integer>> c1=new Cla1<Cla1<Integer>>(new Cla1<Integer>(10));//泛型類里面的類型還是泛型類,傳參的時候傳的是泛型類的引用System.out.println(c1.getData().getData());//c1.getData()是調用的當做參數傳入的泛型類,Cla1<Integer> a,就相當于這樣的//此時a是泛型類類型,需要再對a取內容才能得到真正的a的數值,也就是當做參數傳進去的那個泛型類的構造方法的數值}
}

泛型類可以繼承泛型類:

abstract class Cla1<T> //一個類型參數
{T a;public Cla1(T a) {this.a=a;}public T getData(){return a;}abstract void printInfo();
}
class Cla2<T,T2> extends Cla1<T> //Cla2繼承Cla1同時還可以增加泛型的個數,這里增加了T2
{T2 b;public Cla2(T a,T2 b) {super(a);this.b=b;}public T2 getDataB(){return b;}@Overridevoid printInfo() {//如果這個類也是抽象類的話,就不用在將父類里面的抽象方法給補全了System.out.println("繼承的類是泛型抽象類,所以要在子類里面實現抽象方法的方法體");}
}
public class Main {public static void main(String[] args) {	Cla2<Integer,String> c2=new Cla2<Integer,String>(110,"String");System.out.println(c2.getData());System.out.println(c2.getDataB());c2.printInfo();}

泛型類可以實現繼承泛型接口:

interface Cla1<T>
{abstract void printfInfo(T t);//在接口中public和abstract可以省略,默認就是public和abstract
}
class Cla2<T> implements Cla1<T>
{public void printfInfo(T t){System.out.println("泛型類繼承泛型接口");}
}
public class Main {public static void main(String[] args) {Cla2<String> c1=new Cla2<String>();c1.printfInfo("");}
}

限制泛型可用類型:

  • 在定義泛型類別的時候,默認在實例化泛型類的時候可以使用任何類型,但是如果要限制使用泛型類型時,只能用某個特定類型或者是其子類型才能實例化該類型時,可以在定義類型時,使用extends關鍵字指定這個類型必須是繼承某個類或者實現某個接口。例如:class Cla11<T estends Move>這里Move是接口interface move這就要求T是接口Move類型的。接口是一個模版,需要類來繼承這個接口來實現才能實例化,所以說繼承了Move這個接口的類都屬于T extren Move。這里就要求是繼承了Move接口的類的類型。class Cla1<T extends Animal>這里Animal是自己定義的一個類,那么T extends Animal表示T只能是Animal類型或者其子類類型。
  • 當沒有指定泛型繼承的類型或者接口時,默認使用extends Object,所以默認情況下任何類型都可以作為參數傳入。

限制使用泛型類型,只能用某個特定類型或者是其子類型才能實例化該類型:

interface Cla1<T extends String>
{abstract void printfInfo(T t);//在接口中public和abstract可以省略,默認就是public和abstract
}
class Cla2<T extends String> implements Cla1<T>//限制泛型只能用某個特定類型或者是其子類型使用extends繼承,限制使用泛型類型為String類型
{T str;public Cla2(T str) {this.str=str;}public void printfInfo(T t){System.out.println(str);System.out.println("泛型類繼承泛型接口");}
}
class Cla3<T extends String,T2 extends Integer > extends Cla2<T>
{T2 in;public Cla3(T str,T2 in) {super(str);this.in=in;}public void printfInfo(T t){System.out.println("父類:"+str+" 子類:"+in);}
}
public class Main {public static void main(String[] args) {Cla2<String> c1=new Cla2<String>("父類");c1.printfInfo(" ");Cla3<String,Integer> c2=new Cla3<String,Integer>("子類",10);c2.printfInfo(" ");}
}

類型通配符聲明:

  • 同一泛型類,如果實例化時給定的實際類型不同,則這些實例的類型是不兼容的,不能相互賦值。
  • 泛型類實例之間的不見兼容性會帶來使用的不方便。我們可以使用泛型通配符<?>聲明泛型類的變量就可以解決這個問題。
  • 和限制泛型的上限相似,同樣可以使用extends關鍵字限定通配類型的上限:<? extends 為某種類型>比如:<? extends String>
  • 還可以使用super關鍵詞將通配符匹配類型限定為某個類型及其父類型
class Animal
{}
class Dog extends Animal
{}
class Cla1<T>
{T a;public Cla1(T a) {this.a=a;}T getData(){return a;}
}
public class Main {public static void main(String[] args) {Cla1<String> c1=new Cla1<String>("String");System.out.println(c1.getData());Cla1<Double> c2=new Cla1<Double>(1.23);System.out.println(c2.getData());//c1=c2;不允許這樣會報錯,因為不是一個類型的Cla1<?> c3;//使用通配符,即可不用限制類型c3=c1;c3=c2;Cla1<? extends String> c4;c4=c1;//c4=c2;因為限制了為String類型所以會報錯Cla1<Dog> c5=new Cla1<Dog>(new Dog());Cla1<Object> c7=new Cla1<Object>(new Object());Cla1<? super Dog> c6;//使用super關鍵詞將通配符匹配類型限定為某個類型及其父類型,c6必須是Dog的父類c6=c5;Cla1<? super Animal> c8;c8=c7;}
}

泛型方法:

  • 不僅類可以聲明泛型,類中的方法也可以聲明僅用于自身的泛型,這種方法叫做泛型方法。其定義格式為:訪問修飾符 <泛型列表> 返回類型 方法名(){}
  • 在泛型列表中聲明的泛型,可用于該方法的返回類型聲明、參數類型聲明和方法代碼中的局部變量的類型聲明。
  • 類中的其他方法不能使用當前方法聲明的泛型。
  • 泛型方法更加靈活,它可以不受泛型類的約束。比方法重載更加靈活。
  • 提示: 是否擁有泛型方法,與其所在的類是否是泛型類沒有關系,要定義泛型方法,只需要將泛型參數列表置于返回值前。
  • 什么時候使用泛型方法,而不是泛型類呢? 添加類型約束條件只作用于一個方法的多個參數之間、而不涉及到類中的其他方法時。 施加類型約束的方法為靜態方法,只能將其定義為泛型方法,因為靜態方法不能使用其所在類的類型參數。
  • 注意: 同樣泛型方法也可以對齊進行限制和在泛型類里面的限制一樣。T在編譯的時候會重置為該類型在類中聲明是所繼承的父類。比如:<T> T printInfo(T t)T默認是繼承Object的,所以在編譯的時候會重置為Object,而<T extends Animal>在編譯的時候會重置為Animal。
class Animal
{void eat(){System.out.println("動物吃");}
}
class Dog extends Animal
{void eat(){System.out.println("狗啃骨頭");}
}
class A<T>
{void printInfo(T t){System.out.println(t);}
}
class B
{<T> T printInfo(T t){//T僅對本方法有效,可用于該方法的返回類型聲明和該方法的參數類型聲明T a;//可用于方法代碼中的局部變量的類型聲明System.out.println(t);return t;}<T,T2> void printInfo(T t,T2 t2){//一個泛型方法有多個泛型參數,這也是個泛型方法的重載//System.out.println(t+t2);這樣寫不允許,必須分開寫,因為還沒有實例化,類型不確定,不能相加System.out.println(t);System.out.println(t2);}<T extends Animal> void printInfo2(T t)//施加泛型方法的類型約束{t.eat();}static <T extends Animal> void printInfo3(T t)//施加泛型方法的類型約束{t.eat();}
}
public class Main {public static void main(String[] args) {A<String> a=new A<String>();a.printInfo("String");B b=new B();b.printInfo("String");b.printInfo('c');b.printInfo(1213);b.printInfo(1,"str");b.printInfo2(new Dog());b.printInfo2(new Animal());B.printInfo3(new Animal());B.printInfo3(new Dog());//靜態方法本身就是和類是脫離的,可以直接通過類名來調用靜態方法}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272087.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272087.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272087.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

不生效 設置了viewport_配置viewport

最近項目中需要開發內嵌的H5頁面&#xff0c;viewport不是很熟悉&#xff0c;故來翻譯一下此篇文件加深理解原文配置viewportIOS上的safari使用一種縮放的工作模式來展示pc端的網頁&#xff0c;如果默認的設置對你的網頁展示不友好&#xff0c;推薦你改變veiwport默認配置&…

Linux文件操作實用筆記

Linux系統遵循一切皆是操作文件的規則。所以想用好Linux系統&#xff0c;就必須要掌握文件相關的操作。 1、創建文件命令&#xff1a;touch 語法格式&#xff1a; touch filename #filename 文件名稱。 比如 touch hello.txt就會在當前木創建一個hello.txt的文件。 說明&#x…

安裝完CentOS 7 后必做的七件事

CentOS是最多人用來運行服務器的 Linux 版本&#xff0c;最新版本是 CentOS 7。當你興趣勃勃地在一臺主機或 VPS 上安裝 CentOS 7 后&#xff0c;首要的工作肯定是加強它的安全性&#xff0c;以下列出的七件事&#xff0c;是你進一步配置系統和安裝其他軟件前必須做的。 1. 更改…

python顯示小數點后幾位數_python窗口編程-3:數位處理(整數)

我們在上一次課程中(python窗口編程-2&#xff1a;風格與布局 )&#xff0c;制作了完整的計算器窗口界面&#xff0c;只是那個窗口沒有真正的功能&#xff0c;是點擊任何按鈕都會關閉。這一次&#xff0c;我們加入一些事件處理的功能&#xff0c;讓它成為一個正常工作的窗口程序…

Linux文件目錄基礎筆記

1、進入目錄名稱&#xff1a;cdcd命令主要是方便用戶切換到不同目錄的指令。比如&#xff1a;cd #只執行cd命令默認進入root的根目錄cd /home #進入home目錄&#xff0c;如果home目錄有testdir目錄的話&#xff0c;可以執行 cd testdir 進入testdir目錄。2、創建目錄命令&#…

eclipse安卓工程的構建、配置連接模擬器、安卓工程結構介紹

安卓工程構建及第一個安卓程序運行&#xff1a; 首先新建安卓工程&#xff1a; 然后填寫APP信息&#xff0c;下面的包名一般都是公司域名的倒寫&#xff0c;包名中不能有中文&#xff0c;否則會報錯。 然后配置一些安卓app的選項 有關app啟動的圖標&#xff08;就像QQ的企鵝一…

android eclipse 導入idea項目

將以下代碼復制到.project中 <?xml version"1.0" encoding"UTF-8"?> <projectDescription> <name>IDEATest</name> <comment/> <projects/> <buildSpec> <buildCommand> <name>com.android.ide.…

Linux中su和sudo的用法整理

一、為什么會有su和sudo命令&#xff1f;主要是因為在實際工作當中需要在Linux不同用戶之間進行切換。root用戶權限最高很多時候需要root用戶才能執行一些關鍵命令。所以需要臨時切換為root用戶。工作完成后&#xff0c;考慮到系統的安全性避免誤操作需要切換為普通用戶。su和s…

codeforces 650B - Image Preview

題意&#xff1a;給你n個照片&#xff0c;從第一個照片開始看&#xff0c;如果一張照片是w&#xff0c;那么要花費b時間去反轉他&#xff0c;否則不用反轉&#xff0c;看一張從來沒看過的照片要1時間&#xff0c; 從一張滑動到另一張要a時間。如果一張照片看過&#xff0c;則不…

asp js單步調試_如何使用Chrome的控制臺高效的調試Javascript代碼?

引言在我們的日常開發中我們常常會遇到JavaScript的調試問題&#xff0c;而我們解決問題的傳統解決方案就是使用大量的console.log或者console對象的其他方法&#xff0c;這會給我們帶來很多不便&#xff0c;特別是遇到復雜問題的時候&#xff0c;可能會出現大量的console.log&…

安卓App的啟動過程、安卓布局分類及布局和頁面的關系

Android App 啟動流程: 當你想要啟動一個app時&#xff0c;首先得點擊該app桌面圖標。那點擊圖標時到底發生了什么呢&#xff1f;先看個理論知識 .Launcher: launcher其實就是一個app&#xff0c;從功能上說&#xff0c;是對手機上其他app的一個管理和啟動&#xff0c;從代碼…

Linux文件默認權限和umask筆記

關于Linux文件默認權限的問題&#xff0c;可以實際先嘗試一下如下命令&#xff1a;root用戶登錄[rootlocalhost test]# touch file1[rootlocalhost test]# ls-l file1-rw-r--r-- 1 root root 0 May 5 08:28 file1 #輸出結果 對應的數字權限 644[rootlocalhost test]# touch fi…

Android相對布局(RelativeLayout)常用屬性、練習使用按鍵、文本框等控件、線性布局(LinearLayout)屬性

RelativeLayout中子控件常用屬性&#xff1a; 子控件默認是從父控件的左上角開始排列的 相對于父控件 android:layout_alignParentTop"true" 和父控件的頂部對齊android:layout_alignParentBottom"true" 和父控件的底部對齊android:layout_alignPar…

Seata AT模式

基本思路 先決條件 支持本地ACID事務的關系數據庫。通過JDBC訪問數據庫的Java應用程序。 整體機制 從兩個階段提交協議的演變&#xff1a; 階段1&#xff1a;在同一本地事務中提交業務數據和回滾日志&#xff0c;然后釋放本地鎖和連接資源。階段2&#xff1a; 對于提交情況…

自媒體各大平臺收益對比_哪些自媒體平臺沒有新手期,適合小白擼收益?

2-26把我設置為星標&#xff0c;不錯過每一次的干貨&#xff5e;各大自媒體平臺的新手期總是讓小白們望而卻步&#xff0c;特別是百家號審核非常嚴格&#xff0c;如果沒思路、沒人指導&#xff0c;過新手有難度。不過&#xff0c;還是有很多平臺對新手寶寶很友好&#xff0c;沒…

Linux關于文件的權限筆記

1、調整文件的權限命令&#xff1a;chmodLinux的每個文件都定義了文件的擁有者&#xff1a;u(user)、擁有組&#xff1a;g&#xff08;group&#xff09;、其他人&#xff1a;o&#xff08;others&#xff09;權限&#xff0c;對應的權限用rwx的組合來定義。使用chmod命令&…

presentViewController和pushViewController

iPhone開發中從一個視圖跳到另一個視圖有三種方法&#xff1a;1、self.view addSubView:view 、self.window addSubView,需要注意的是&#xff0c;這個方法只是把頁面加在當前頁面。此時在用self.navigationControler.pushViewController和 pushViewController 是不行的。要想使…