「本文已參與好文召集令活動,點擊查看:後端、大前端雙賽道投稿,2萬元獎池等你挑戰!」前端
雖然寫了一段時間的 Java 代碼,可是一直以來只要看到泛型,仍是會摸不着頭腦選擇性放棄。可是今天在看公司大佬的代碼發現不少地方會用到泛型,因此今天就整理一下我理解的泛型。java
泛型程序設計(generic programming)是程序設計語言的一種風格或範式。泛型容許程序員在強類型程序設計語言中編寫代碼時使用一些之後才指定的類型,在實例化時做爲參數指明這些類型。 泛型的定義主要有如下兩種: 1⃣️ 在程序編碼中一些包含類型參數的類型,也就是說泛型的參數只能夠表明類,不能表明個別對象。 2⃣️ 在程序編碼中一些包含參數的類。其參數能夠表明類或對象等等。程序員
👆上面的解釋來自百度百科,簡單的說 泛型是一種代碼範式。後端
Java 泛型的參數只能夠表明類,不能表明個別對象。因爲 Java 泛型的類型參數之實際類型在編譯時會被消除,因此沒法在運行時得知其類型參數的類型,並且沒法直接使用基本值類型做爲泛型類型參數。markdown
Java 泛型設計原則:ide
把類型明確的工做推遲到建立對象或調用方法的時候纔去明確的特殊的類型。只要在編譯時期沒有出現警告,那麼運行時期就不會出現 ClassCastException
異常。post
下面是簡單的泛型的例子:this
public class Generic {
public static void main(String[] args) {
// C 能夠接受 String
C<String> stringC = new C<>("Hello world");
System.out.println(stringC);
// C 能夠接受 Integer
C<Integer> integerC = new C<>(100);
System.out.println(integerC);
}
}
// C 能夠接受任意類型數據的初始化
class C<T> {
private T item;
public C(T t){
item = t;
}
@Override
public String toString() {
return item + "";
}
}
複製代碼
T、E、K、V 本質上都是通配符。編碼有時候講究約定俗成。好比咱們能夠用 A-Z 之間的任何一個字母均可以表示通配符,並不會影響程序的正常運行。一般狀況下 T、E、K、V 是這樣約定的:編碼
?
表示不肯定的 Java 類型T ( type )
表示具體的一個 Java 類型K V ( key value )
分別表明 Java 鍵值中的 Key ValueE ( element )
表明 Element上界通配符 ? extends T
spa
例如 List< ? extends Number>
目的是爲了接受List<Integer> or List<Long>
的數據類型。
下界通配符 ? super T
例如 List<? super Number>
目的是爲了彌補只能存放一種特定類型數據的不足。
public class Generic {
public static void main(String[] args) {
// 能夠
List<? super Number> list = new ArrayList<>();
list.add(10);
list.add(20L);
list.add(20.2);
System.out.println(list);
List<Integer> list1 = new ArrayList<>();
List<Long> list2 = new ArrayList<>();
list1.add(10);
list1.add(20);
list2.add(10L);
list2.add(20L);
read(list1);
read(list2);
}
private static void read(List< ? extends Number> list) {
Number first = list.get(0);
Number last = list.get(list.size() - 1);
System.out.println("first = " + first.toString() + " last = " + last.toString());
}
}
複製代碼
最後看一下 PECS(Producer Extends Consumer Super)原則:
// 多參數泛型
class Person<N, A, S> {
private N name;
private A age;
private S sex;
Person(N name, A age, S sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public N getName() {
return name;
}
public void setName(N name) {
this.name = name;
}
public A getAge() {
return age;
}
public void setAge(A age) {
this.age = age;
}
public S getSex() {
return sex;
}
public void setSex(S sex) {
this.sex = sex;
}
@Override
public String toString() {
return "姓名:" + name + ",年齡:" + age + ",性別:" + sex;
}
}
// 使用
public class Generic {
public static void main(String[] args) {
Person<String, Integer, Character> person = new Person<String, Integer, Character>("蛋炒飯", 28, '男');
printPerson(person);
// 姓名:蛋炒飯,年齡:28,性別:男
}
// 泛型方法
private static <T> void printPerson(T person){
if ( person != null) {
System.out.println(person);
}
}
}
複製代碼