在本教程中,我們將通過示例了解Java泛型,如何創(chuàng)建泛型類和方法及其優(yōu)勢。
在Java中,泛型有助于創(chuàng)建可與不同類型的對象(數(shù)據(jù))一起使用的類,接口和方法。因此,允許我們重用我們的代碼。
注意:泛型泛型不適用于基本類型(int,float,char等)。
要了解在Java中如何使用泛型,我們可以使用ArrayListJava集合框架的類。
ArrayList類是泛型類的一個示例。我們可以使用ArrayList來存儲任何類型的數(shù)據(jù)。例如
import java.util.ArrayList; class Main { public static void main(String[] args) { //創(chuàng)建一個數(shù)組列表來存儲Integer 數(shù)據(jù) ArrayList<Integer> list1 = new ArrayList<>(); list1.add(4); list1.add(5); System.out.println("ArrayList of Integer: " + list1); //創(chuàng)建數(shù)組列表來存儲String 數(shù)據(jù) ArrayList<String> list2 = new ArrayList<>(); list2.add("Four"); list2.add("Five"); System.out.println("ArrayList of String: " + list2); //創(chuàng)建數(shù)組列表來存儲Double 數(shù)據(jù) ArrayList<Double> list3 = new ArrayList<>(); list3.add(4.5); list3.add(6.5); System.out.println("ArrayList of Double: " + list3); } }
輸出結(jié)果
ArrayList of Integer: [4, 5] ArrayList of String: [Four, Five] ArrayList of Double: [4.5, 6.5]
在上面的示例中,我們使用了相同的ArrayList類來存儲Integer,String和Double類型的元素。 由于Java泛型,這是可能的。
在這里,請注意這行,
ArrayList<Integer> list1 = new ArrayList<>();
我們在尖括號<>中使用了Integer。 尖括號<>在泛型中稱為類型參數(shù)。
參數(shù)type用于指定泛型類或方法適用的對象(數(shù)據(jù))的類型。
現(xiàn)在我們知道了泛型在Java中的工作方式,讓我們看看如何創(chuàng)建自己的泛型類。
class Main { public static void main(String[] args) { //用整數(shù)數(shù)據(jù)初始化泛型類 GenericsClass<Integer> intObj = new GenericsClass<>(5); System.out.println("泛型類返回: " + intObj.getData()); //用字符串數(shù)據(jù)初始化泛型類 GenericsClass<String> stringObj = new GenericsClass<>("Java Programming"); System.out.println("泛型類返回: " + stringObj.getData()); } } class GenericsClass<T> { //T型變量 private T data; public GenericsClass(T data) { this.data = data; } //返回T類型變量的方法 public T getData() { return this.data; } }
輸出結(jié)果
泛型類返回: 5 泛型類返回: Java Programing
在上面的示例中,我們創(chuàng)建了一個名為GenericsClass的泛型類。此類可用于處理任何類型的數(shù)據(jù)。
class GenericsClass<T> {...}
在此,T表示類型參數(shù)。 在Main類內(nèi)部,我們創(chuàng)建了名為intObj和stringObj的GenericsClass對象。
在創(chuàng)建intObj時,類型參數(shù)T被Integer替換。這意味著intObj使用GenericsClass處理整數(shù)數(shù)據(jù)。
在創(chuàng)建stringObj時,類型參數(shù)T被String替換。 這意味著stringObj使用GenericsClass處理字符串數(shù)據(jù)。
與泛型類相似,我們還可以在Java中創(chuàng)建自己的泛型方法。
class Main { public static void main(String[] args) { //使用Integer數(shù)據(jù)初始化類 DemoClass demo = new DemoClass(); demo.<String>genericsMethod("Java Programming"); } } class DemoClass { //泛型方法 public <T> void genericsMethod(T data) { System.out.println("這是一個泛型方法。"); System.out.println("傳遞給方法的數(shù)據(jù)是 " + data); } }
輸出結(jié)果
這是一個泛型方法。 傳遞給方法的數(shù)據(jù)是: Java Programming
在上面的示例中,我們創(chuàng)建了一個在普通類(DemoClass)內(nèi)部命名的泛型方法genericsMethod。
public <T> void genericMethod(T data) {...}
在此,將類型參數(shù)<T>插入到修飾符(public)之后和返回類型(void)之前。
我們可以通過將實際類型<String>放在方法名前面的括號中來調(diào)用泛型方法。
demo.<String>genericMethod("Java Programming");
注意:在大多數(shù)情況下,我們可以在調(diào)用泛型方法時省略type參數(shù)。這是因為編譯器可以使用傳遞給方法的值來匹配類型參數(shù)。例如,
demo.genericsMethod("Java Programming");
通常,type參數(shù)可以接受任何數(shù)據(jù)類型(原始類型除外)。但是,如果我們只想將泛型用于某些特定類型(例如接受數(shù)字類型的數(shù)據(jù)),則可以使用有界類型。
我們使用extends關(guān)鍵字。例如,
<T extends A>
這意味著T只能接受A的子類型的數(shù)據(jù)。
class GenericsClass <T extends Number> { public void display() { System.out.println("This is a bounded type generics class."); } } class Main { public static void main(String[] args) { //創(chuàng)建一個GenericsClass對象 GenericsClass<String> obj = new GenericsClass<>(); } }
在上面的示例中,我們創(chuàng)建了一個有界類型的泛型類。 在這里,請注意表達式
<T extends Number>
這意味著T只能使用Number的子級數(shù)據(jù)類型(Integer,Double等)。
但是,我們已經(jīng)用String創(chuàng)建了泛型類的對象。這就是為什么當我們運行程序時,我們會得到以下錯誤。
GenericsClass<String> obj = new GenericsClass<>(); ^ reason: inference variable T has incompatible bounds equality constraints: String lower bounds: Number where T is a type-variable: T extends Number declared in class GenericsClass
泛型使我們能夠編寫適用于不同類型數(shù)據(jù)的代碼。例如,
public <T> void genericsMethod(T data) {...}
在這里,我們創(chuàng)建了一個泛型方法。此方法可用于對整數(shù)數(shù)據(jù),字符串數(shù)據(jù)等執(zhí)行操作。
泛型的type參數(shù)提供有關(guān)泛型代碼中使用的數(shù)據(jù)類型的信息。
因此,可以在編譯時識別任何錯誤,比運行時錯誤更容易修復。例如,
//不使用泛型 NormalClass list = new NormalClass(); //調(diào)用NormalClass的方法 list.display("String");
在上面的代碼中,我們有一個普通的類。我們通過傳遞字符串數(shù)據(jù)來調(diào)用此類的名為display()的方法。
在這里,編譯器不知道在參數(shù)中傳遞的值是否正確。但是,讓我們看看如果改用泛型類會發(fā)生什么。
//使用泛型 GenericsClass<Integer> list = new GenericsClass<>(); //調(diào)用GenericsClass的方法 list2.display("String"); 在上面的代碼中,我們有一個泛型類。 在這里,類型參數(shù)表示該類正在處理Integer數(shù)據(jù)。 因此,當字符串數(shù)據(jù)在參數(shù)中傳遞時,編譯器將生成一個錯誤。
集合框架使用Java中的泛型概念。例如,
// 創(chuàng)建一個字符串類型ArrayList ArrayList<String> list1 = new ArrayList<>(); // 創(chuàng)建一個整數(shù)類型ArrayList ArrayList<Integer> list2 = new ArrayList<>();
在上面的示例中,我們使用了相同的ArrayList類來處理不同類型的數(shù)據(jù)。
類似ArrayList,其他集合(LinkedList,Queue,Maps,等等)也是Java的泛型。