【前面的話】java
最近臉好乾,掉皮,須要買點化妝品了。數組
Java泛型好好學習一下。安全
【定義】學習
1、泛型的定義主要有如下兩種:測試
不論使用那個定義,泛型的參數在真正使用泛型時都必須做出指明。this
2、使用泛型的目的:編碼
【Java泛型的幾種類型代碼】spa
1、不使用泛型的代碼設計
咱們定義一個Person類,包含三個屬性x,y,z。在咱們開始定義地時候,咱們也不知道這三個屬性是用來幹什麼的,因此咱們定義爲Object類型。可是在使用的時候,咱們分別對x,y,z賦予了int,double,String類型,因此在取出的時候,咱們須要把這三個類型值進行強制轉換。以下代碼:code
1. Person.java
1 public class Person { 2 private Object x; 3 private Object y; 4 private Object z; 5 //使用Object類型。能夠轉化爲任何類型 6 public Object getX() { 7 return x; 8 } 9 public void setX(Object x) { 10 this.x = x; 11 } 12 public Object getY() { 13 return y; 14 } 15 public void setY(Object y) { 16 this.y = y; 17 } 18 public Object getZ() { 19 return z; 20 } 21 public void setZ(Object z) { 22 this.z = z; 23 } 24 }
2. NoGenericTest.java
1 public class NoGenericTest { 2 public static void main(String[]args){ 3 Person boy=new Person(); 4 boy.setX(20); 5 boy.setY(22.2); 6 boy.setZ("帥哥TT"); 7 //這裏根據設置的不一樣類型的值,咱們須要進行強制類型轉化。 8 int x=(Integer)boy.getX(); 9 double y=(double)boy.getY(); 10 String z=(String)boy.getZ(); 11 12 System.out.println(x); 13 System.out.println(y); 14 System.out.println(z); 15 } 16 }
3. 運行結果
1 20 2 22.2 3 帥哥TT
2、使用一個類型變量泛型的代碼
咱們定義一個泛型類Person,定義三個屬性x,y,z,在測試類中,咱們設置屬性的值,並打印。
1. Person.java
1 public class Person<T> { 2 private T x; 3 private T y; 4 private T z; 5 public T getX() { 6 return x; 7 } 8 public void setX(T x) { 9 this.x = x; 10 } 11 public T getY() { 12 return y; 13 } 14 public void setY(T y) { 15 this.y = y; 16 } 17 public T getZ() { 18 return z; 19 } 20 public void setZ(T z) { 21 this.z = z; 22 } 23 }
2. GenericTest.java
1 public class GenericTest { 2 public static void main(String[]args){ 3 Person boy=new Person(); 4 boy.setX(20); 5 boy.setY(22.2); 6 boy.setZ("帥哥TT"); 7 //不用進行類型轉化 8 System.out.println(boy.getX()); 9 System.out.println(boy.getY()); 10 System.out.println(boy.getZ()); 11 } 12 }
3. 運行結果
1 20 2 22.2 3 帥哥TT
3、使用兩個類型變量泛型的代碼
咱們定義一個泛型類Person,定義兩個屬性x,y,使用了兩種不一樣的類型變量,在測試類中,咱們設置屬性的值,並打印。
1. Person.java
1 public class Person<T1,T2> { 2 private T1 x; 3 private T2 y; 4 public T1 getX() { 5 return x; 6 } 7 public void setX(T1 x) { 8 this.x = x; 9 } 10 public T2 getY() { 11 return y; 12 } 13 public void setY(T2 y) { 14 this.y = y; 15 } 16 }
2. GenericTest.java
1 public class GenerricTest { 2 public static void main(String[] args){ 3 Person<String,Integer> boy=new Person<String,Integer>(); 4 boy.setX("帥哥TT"); 5 boy.setY(20); 6 System.out.println(boy.getX()); 7 System.out.println(boy.getY()); 8 } 9 10 }
3. 運行結果
1 帥哥TT 2 20
4、使用泛型的繼承
咱們定義一個泛型類Person,定義兩個屬性x,y,而後定義另外一個泛型類Boy,定義屬性z,Boy繼承Person類,在測試類中,咱們設置屬性的值,並打印。
1. Person.java
1 public class Person<T1,T2> { 2 private T1 x; 3 private T2 y; 4 public T1 getX() { 5 return x; 6 } 7 public void setX(T1 x) { 8 this.x = x; 9 } 10 public T2 getY() { 11 return y; 12 } 13 public void setY(T2 y) { 14 this.y = y; 15 } 16 }
2. Boy
1 public class Boy<T1,T2,T3>extends Person<T1,T2> { 2 private T3 z; 3 public T3 getZ() { 4 return z; 5 } 6 public void setZ(T3 z) { 7 this.z = z; 8 } 9 }
3. GenericTest.java
1 public class GenericTest { 2 public static void main(String[] args){ 3 Boy<String,Integer,Double> boy=new Boy<String,Integer,Double>(); 4 boy.setX("帥哥TT"); 5 boy.setY(20); 6 boy.setZ(200000.22); 7 8 System.out.println(boy.getX()); 9 System.out.println(boy.getY()); 10 System.out.println(boy.getZ()); 11 } 12 }
4. 運行結果
1 帥哥TT 2 20 3 200000.22
5、使用泛型的接口
咱們定義一個泛型接口Person,定義兩個方法,而後定義另外一個泛型類Boy,實現泛型接口Person,定義屬性x,y,z,在測試類中,咱們設置屬性的值,並打印。
1. Person.java
1 public interface Person<T1,T2> { 2 public T1 getX(); 3 public T2 getY(); 4 }
2. Boy
1 public class Boy<T1,T2,T3>implements Person<T1,T2> { 2 private T1 x; 3 private T2 y; 4 private T3 z; 5 public T1 getX() { 6 return x; 7 } 8 public void setX(T1 x) { 9 this.x = x; 10 } 11 public T2 getY() { 12 return y; 13 } 14 public void setY(T2 y) { 15 this.y = y; 16 } 17 public T3 getZ() { 18 return z; 19 } 20 public void setZ(T3 z) { 21 this.z = z; 22 } 23 24 }
3. GenericTest.java
1 public class GenericTest { 2 public static void main(String[] args){ 3 Boy<String,Integer,Double> boy=new Boy<String,Integer,Double>(); 4 boy.setX("帥哥TT"); 5 boy.setY(20); 6 boy.setZ(200000.22); 7 System.out.println(boy.getX()); 8 System.out.println(boy.getY()); 9 System.out.println(boy.getZ()); 10 } 11 }
4. 運行結果
1 帥哥TT 2 20 3 200000.22
6、使用泛型方法
說明一下,定義泛型方法時,必須在返回值前邊加一個<T>,來聲明這是一個泛型方法,持有一個泛型T,而後才能夠用泛型T做爲方法的返回值。
定義一個普通類Person,定義一個泛型方法,以下代碼:
1. Person.java
1 public class Person{ 2 public static<T>T getMiddle(T[]a){ 3 return a[a.length/2]; 4 } 5 public static void main(String [] args){ 6 String[]name={"帥哥TT","帥哥TT1","帥哥TT2"}; 7 String middle=Person.<String>getMiddle(name); 8 System.out.println(middle); 9 10 Integer[]num={20,22,25}; 11 Integer middle1=Person.<Integer>getMiddle(num); 12 System.out.println(middle1); 13 14 Double[]num1={20.0,22.2,25.5}; 15 Double middle2=Person.<Double>getMiddle(num1); 16 System.out.println(middle2); 17 } 18 }
2. 運行結果
1 帥哥TT1 2 22 3 22.2
7、類型變量的限定
以下代碼,咱們在方法min中定義了一個變量smallest類型爲T,這說明了smallest能夠是任何一個類的對象,咱們在下面的代碼中須要使用compareTo方法, 可是咱們沒有辦法肯定咱們的T中含有CompareTo方法,因此咱們須要對T進行限定,在代碼中咱們讓T繼承Comparable類。以下:
1 public static<T extends Comparable>T min(T[]a)
1. Person.java
1 public class Person{ 2 public static<T extends Comparable>T min(T[]a){ 3 if(a==null||a.length==0){ 4 return null; 5 } 6 T smallest=a[0]; 7 for(int i=1;i<a.length;i++){ 8 if(smallest.compareTo(a[i])>0){ 9 smallest=a[i]; 10 } 11 } 12 return smallest; 13 } 14 public static void main(String [] args){ 15 Integer[]num={20,25,30,10}; 16 Integer middle=Person.<Integer>min(num); 17 System.out.println(middle); 18 } 19 }
2. 運行結果
1 10
【Java泛型理解】
1、類型擦除
正確理解泛型概念的首要前提是理解類型擦除(type erasure)。 Java中的泛型基本上都是在編譯器這個層次來實現的。在生成的Java字節代碼中是不包含泛型中的類型信息的。使用泛型的時候加上的類型參數,會被編譯器在編譯的時候去掉。這個過程就稱爲類型擦除。如在代碼中定義的List<Object>和List<String>等類型,在編譯以後都會變成List。JVM看到的只是List,而由泛型附加的類型信息對JVM來講是不可見的。Java編譯器會在編譯時儘量的發現可能出錯的地方,可是仍然沒法避免在運行時刻出現類型轉換異常的狀況。
不少泛型的奇怪特性都與這個類型擦除的存在有關,包括:
2、最佳實踐
在使用泛型的時候能夠遵循一些基本的原則,從而避免一些常見的問題。
【參考資料】
【後面的話】
好好學習。
——TT