新聞中心
我今天聊聊Java中的泛型, 它是一個廣泛使用但討論較少的主題。我們經(jīng)常會使用它,但大多數(shù)開發(fā)人員并沒有真正了解它。

精河網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁設計、網(wǎng)站建設、微信開發(fā)、APP開發(fā)、成都響應式網(wǎng)站建設公司等網(wǎng)站項目制作,到程序開發(fā),運營維護。創(chuàng)新互聯(lián)建站從2013年成立到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設就選創(chuàng)新互聯(lián)建站。
Java開發(fā)中你們肯定都用過List或者ArrayList。那你們應該記得如何定義他們吧?
List list = new ArrayList<>(); // 這里的Integer 就是使用了泛型
這就是我們聲明的方式。所以,我們使用了泛型。這里,
那如果我們不指定類型呢?
List numList = new ArrayList<>(); //不指定類型
如果我們像上面這樣定義列表,我們就可以將從 Object 超類擴展的任何類型的數(shù)據(jù)添加到列表中。
所以添加泛型后,我們可以實現(xiàn)此列表的類型安全。
泛型意味著參數(shù)化類型。Java 讓我們創(chuàng)建一個類、接口和方法,可以在泛型域中與不同類型的數(shù)據(jù)(對象)一起使用。
泛型的優(yōu)點是:
- 代碼可重用性——我們可以使用具有多種對象類型的通用代碼
- 編譯時類型檢查——Java 將在編譯時檢查泛型代碼是否有錯誤
- 類型安全——我們可以限制添加不必要的數(shù)據(jù)
- 集合中的用法——集合需要對象類型來處理數(shù)據(jù)
讓我們舉個例子來解釋為什么我們需要泛型。
想象一下,您必須使用打印機類打印數(shù)字和文本。打印機有一種在創(chuàng)建數(shù)據(jù)時接受數(shù)據(jù)的方法。
在傳統(tǒng)方式中,我們必須創(chuàng)建 2 個類,因為我們有 2 種數(shù)據(jù)類型:數(shù)字(整數(shù))和文本(字符串)
public class TextPrinter {
private final String data;
public TextPrinter(String data) {
this.data = data;
}
public void print() {
System.out.println("print::: " + data);
}
}
public class NumberPrinter {
private final Integer data;
public NumberPrinter(Integer data) {
this.data = data;
}
public void print() {
System.out.println("print::: " + data);
}
}
使用:
public class GenericsMain {
public static void main(String[] args) {
NumberPrinter numberPrinter = new NumberPrinter(5);
numberPrinter.print(); // 輸出 print::: 5
TextPrinter textPrinter = new TextPrinter("Hello");
textPrinter.print(); // 輸出 print::: Hello
}
}
有沒有覺得代碼重復了?唯一的區(qū)別就是數(shù)據(jù)類型不同!
下面我們利用泛型來改造一下,使它成為一個通用的類型。
public class Printer {
private final T data;
public Printer(T data) {
this.data = data;
}
public void print() {
System.out.println("print::: " + data);
}
}
使用:
Printer integerPrinter = new Printer<>(5);
integerPrinter.print(); // 輸出 print::: 5
Printer stringPrinter = new Printer<>("Hello");
stringPrinter.print(); // 輸出 print::: Hello
Printer doublePrinter = new Printer<>(45.34);
doublePrinter.print(); // 輸出 print::: 45.34
Printer longPrinter = new Printer<>(5L);
longPrinter.print();z //輸出 print::: 5
現(xiàn)在我們就只寫了一個類,T用來表示作為通用標準的類型。我們甚至可以為其他數(shù)據(jù)類型(例如 Double/Long)創(chuàng)建打印對象。代碼可重用性是通過風格實現(xiàn)的。
我們還可以創(chuàng)建多個類型的通用類。如下:
public class MultiPrinter {
private final T data1;
private final V data2;
public MultiPrinter(T data1, V data2) {
this.data1 = data1;
this.data2 = data2;
}
public void print() {
System.out.println("print::: " + data1 + " : " + data2);
}
}
MultiPrinter multiPrinter = new MultiPrinter<>(5, "Hello");
multiPrinter.print(); // 輸出 print::: 5 : Hello
Java 類型命名約定:
- E - 元素(用于集合)
- K — 鍵(在地圖中使用)
- N——數(shù)字
- T——類型
- V - 值(在地圖中使用)
- S、U、V 等 — 第二、第三、第四類型
有界泛型
這是泛型的高級版本。我們可以通過有界泛型來限制更多并實現(xiàn)更多類型安全。
假設我們有一個AnimalPrinter類,它只能打印動物詳細信息。不允許與其他物體一起使用。如何實現(xiàn)這一目標?
public class Animal {
private final String name;
private final String color;
private final Integer age;
public Animal(String name, String color, Integer age) {
this.name = name;
this.color = color;
this.age = age;
}
public String getName() {
return name;
}
public String getColor() {
return color;
}
public Integer getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Animal animal = (Animal) o;
return Objects.equals(name, animal.name) && Objects.equals(color, animal.color) && Objects.equals(age, animal.age);
}
@Override
public int hashCode() {
return Objects.hash(name, color, age);
}
}
public class Cat extends Animal {
public Cat(String name, String color, Integer age) {
super(name, color, age);
}
}
public class Dog extends Animal {
public Dog(String name, String color, Integer age) {
super(name, color, age);
}
}
public class AnimalPrinter {
private final T animalData;
public AnimalPrinter(T animalData) {
this.animalData = animalData;
}
public void print() {
System.out.println("Name::: " + animalData.getName());
System.out.println("Color::: " + animalData.getColor());
System.out.println("Age::: " + animalData.getAge());
}
}
在這個類中,T 擴展 Animal 部分完成了工作!我們限制了狗和貓的通用性!
AnimalPrinter animalPrinter1 = new AnimalPrinter<>(new Cat("Jim", "brown", 2));
animalPrinter1.print();
AnimalPrinter animalPrinter2 = new AnimalPrinter<>(new Dog("Rocky", "black", 5));
animalPrinter2.print();
多重界限
假設我們想向打印機通用功能添加更多功能。我們可以這樣實現(xiàn)。
public class AnimalPrinter {
..................
}
我使用 Serialized 接口提供了 Serialized 功能。這里有一些重要的事情需要記住。
- 我們必須在子類(Cat 和 Dog)中實現(xiàn)接口。
- 類應該放在第一位,然后是 & 和接口。
- 由于 Java 不支持多重繼承,因此只能擴展 1 個類。
泛型通配符
通配符由問號?表示 在 Java 中,我們用它們來指代未知類型。這可以用作泛型的參數(shù)類型。然后它將接受任何類型。在下面的代碼中,我使用通配符將任何對象的列表用作方法參數(shù)。
public static void printList(List> list) {
System.out.println(list);
}
printList(
Arrays.asList(
new Cat("Jim", "brown", 2),
new Dog("Rocky", "black", 5)
)
);
printList(Arrays.asList(50, 60));
printList(Arrays.asList(50.45, 60.78));
// output:
// [generics.Cat@b1fa3959, generics.Dog@62294cd9]
// [50, 60]
// [50.45, 60.78]
列表現(xiàn)在可以是任何類型!
上限通配符
考慮這個例子:
public static void printAnimals(List animals) {
animals.forEach(Animal::eat);
}
如果我們想象Animal的子類型,例如Dog ,我們就不能將此方法與Dog列表一起使用,即使Dog是Animal的子類型。我們可以使用通配符來做到這一點。
public static void printAnimals(List extends Animal> animals) {
...
}
現(xiàn)在,此方法適用于Animal類型及其所有子類型。
printAnimals(
Arrays.asList(
new Cat("Jim", "brown", 2),
new Dog("Rocky", "black", 5)
)
);
這稱為上限通配符,其中Animal類型是上限。
下界通配符
我們還可以指定具有下限的通配符,其中未知類型必須是指定類型的超類型??梢允褂胹uper 關(guān)鍵字后跟特定類型來指定下限。
例子:
public static void addIntegers(List super Integer> list){
list.add(new Integer(70));
}
通用方法
想象一下,我們需要一種采用不同數(shù)據(jù)類型并執(zhí)行某些操作的方法。我們可以為此創(chuàng)建一個通用方法并重用它。
public static void call(T data) {
System.out.println(data);
}
call("hello");
call(45);
call(15.67);
call(5L);
call(new Dog("Rocky", "black", 5));
/* output:
hello
45
15.67
5
generics.Dog@62294cd9
*/
如果我們想返回數(shù)據(jù)而不是 VOID,我們也可以這樣做。
public static T getData(T data) {
return data;
}
System.out.println(getData("Test")); // 輸出 Test
我們也可以在通用方法中接受多種數(shù)據(jù)類型。
public static void getMultiData(T data1, V data2) {
System.out.println("data 1: " + data1);
System.out.println("data 2: " + data2);
}
getMultiData(50, "Shades of Grey"); 文章題目:Java中的泛型,看完這個還不會,我倒立洗頭!
文章源于:http://m.fisionsoft.com.cn/article/dpiohih.html


咨詢
建站咨詢
