我今天聊聊Java中的泛型, 它是一個(gè)廣泛使用但討論較少的主題。我們經(jīng)常會(huì)使用它,但大多數(shù)開發(fā)人員并沒有真正了解它。
Java開發(fā)中你們肯定都用過List或者ArrayList。那你們應(yīng)該記得如何定義他們吧?
List<Integer> list = new ArrayList<>(); // 這里的Integer 就是使用了泛型
這就是我們聲明的方式。所以,我們使用了泛型。這里,<Integer>是我們傳遞的指定類型。那是一個(gè)類型。在我們創(chuàng)建這樣的列表后,您只能將整數(shù)添加到列表中。
那如果我們不指定類型呢?
List numList = new ArrayList<>(); //不指定類型
如果我們像上面這樣定義列表,我們就可以將從 Object 超類擴(kuò)展的任何類型的數(shù)據(jù)添加到列表中。
所以添加泛型后,我們可以實(shí)現(xiàn)此列表的類型安全。
泛型意味著參數(shù)化類型。Java 讓我們創(chuàng)建一個(gè)類、接口和方法,可以在泛型域中與不同類型的數(shù)據(jù)(對(duì)象)一起使用。
泛型的優(yōu)點(diǎn)是:
讓我們舉個(gè)例子來解釋為什么我們需要泛型。
想象一下,您必須使用打印機(jī)類打印數(shù)字和文本。打印機(jī)有一種在創(chuàng)建數(shù)據(jù)時(shí)接受數(shù)據(jù)的方法。
在傳統(tǒng)方式中,我們必須創(chuàng)建 2 個(gè)類,因?yàn)槲覀冇?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 }}
有沒有覺得代碼重復(fù)了?唯一的區(qū)別就是數(shù)據(jù)類型不同!
下面我們利用泛型來改造一下,使它成為一個(gè)通用的類型。
public class Printer<T> { private final T data; public Printer(T data) { this.data = data; } public void print() { System.out.println("print::: " + data); }}
使用:
Printer<Integer> integerPrinter = new Printer<>(5);integerPrinter.print(); // 輸出 print::: 5Printer<String> stringPrinter = new Printer<>("Hello");stringPrinter.print(); // 輸出 print::: HelloPrinter<Double> doublePrinter = new Printer<>(45.34);doublePrinter.print(); // 輸出 print::: 45.34Printer<Long> longPrinter = new Printer<>(5L);longPrinter.print();z //輸出 print::: 5
現(xiàn)在我們就只寫了一個(gè)類,T用來表示作為通用標(biāo)準(zhǔn)的類型。我們甚至可以為其他數(shù)據(jù)類型(例如 Double/Long)創(chuàng)建打印對(duì)象。代碼可重用性是通過風(fēng)格實(shí)現(xiàn)的。
我們還可以創(chuàng)建多個(gè)類型的通用類。如下:
public class MultiPrinter<T, V> { 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<Integer, String> multiPrinter = new MultiPrinter<>(5, "Hello");multiPrinter.print(); // 輸出 print::: 5 : Hello
Java 類型命名約定:
這是泛型的高級(jí)版本。我們可以通過有界泛型來限制更多并實(shí)現(xiàn)更多類型安全。
假設(shè)我們有一個(gè)AnimalPrinter類,它只能打印動(dòng)物詳細(xì)信息。不允許與其他物體一起使用。如何實(shí)現(xiàn)這一目標(biāo)?
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<T extends Animal> { 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()); }}
在這個(gè)類中,T 擴(kuò)展 Animal 部分完成了工作!我們限制了狗和貓的通用性!
AnimalPrinter<Cat> animalPrinter1 = new AnimalPrinter<>(new Cat("Jim", "brown", 2));animalPrinter1.print();AnimalPrinter<Dog> animalPrinter2 = new AnimalPrinter<>(new Dog("Rocky", "black", 5));animalPrinter2.print();
假設(shè)我們想向打印機(jī)通用功能添加更多功能。我們可以這樣實(shí)現(xiàn)。
public class AnimalPrinter<T extends Animal & Serializable> { ..................}
我使用 Serialized 接口提供了 Serialized 功能。這里有一些重要的事情需要記住。
通配符由問號(hào)?表示 在 Java 中,我們用它們來指代未知類型。這可以用作泛型的參數(shù)類型。然后它將接受任何類型。在下面的代碼中,我使用通配符將任何對(duì)象的列表用作方法參數(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)在可以是任何類型!
考慮這個(gè)例子:
public static void printAnimals(List<Animal> animals) { animals.forEach(Animal::eat);}
如果我們想象Animal的子類型,例如Dog ,我們就不能將此方法與Dog列表一起使用,即使Dog是Animal的子類型。我們可以使用通配符來做到這一點(diǎn)。
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)建一個(gè)通用方法并重用它。
public static <T> 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*/
如果我們想返回?cái)?shù)據(jù)而不是 VOID,我們也可以這樣做。
public static <T> T getData(T data) { return data;}System.out.println(getData("Test")); // 輸出 Test
我們也可以在通用方法中接受多種數(shù)據(jù)類型。
public static <T, V> void getMultiData(T data1, V data2) { System.out.println("data 1: " + data1); System.out.println("data 2: " + data2);}getMultiData(50, "Shades of Grey");
本文鏈接:http://www.www897cc.com/showinfo-26-17651-0.htmlJava中的泛型,看完這個(gè)還不會(huì),我倒立洗頭!
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com