1、泛型的引入緣由java
在操做集合的時候,以前方法的定義都是Object類型,向集合中添加對象,都自動向上轉型,加入的元素能夠是任何類型數組
可是,在取出元素的時候,一般想要使用對象的特有功能,就必須向下轉型,此時就可能出現類型轉換異常,存在安全隱患。安全
在JDK1.5時候提出一個解決方案:泛型。ide
2、泛型的定義及好處ui
泛型:是一種應用在編譯時期的安全機制,具體的作法:有點相似於數組的思想,定義操做的時候,指定好要操做的類型信息this
eg:ArrayList<String>:表示該ArrayList只能操做字符串類型的元素,假如要向其中添加Integer類型,就會編譯失敗。spa
<>尖括號中指定被操縱的對象的類型。設計
好處:將運行期間可能出現的異常,轉化爲編譯時期的強制檢驗,避免了強制類型轉換;也提供了設計上的便捷code
3、泛型的擦除和補償對象
泛型擦除:具體指的是編譯器在堆源代碼進行完類型檢查後,在生成字節碼文件的時候,會濾過泛型指定的類型信息,因此
生成的字節碼文件中不含有具體的類型信息--變爲Object或某個範圍,使用泛型擦除主要的目的:其實爲了兼容性,爲了繼續使用
Classloader加載類,同時還要知足之前沒有泛型類的加載,因此就在檢查完類型匹配後,將泛型類型的信息擦除。
泛型補償:當要原本具備泛型的方法在被調用的時候,根據實際類型的Class對象獲取類型信息,自動的添加到原來的地方。
1 import java.util.Iterator; 2 import java.util.TreeSet; 3 4 /*泛型的簡單使用 5 * */ 6 public class GenericsDemo { 7 8 public static void main(String[] args) { 9 //TreeSet在添加元素的時候排序,元素必須可以被比較/或傳給TreeSet一個比較器 10 TreeSet<Unicorn> t = new TreeSet<Unicorn>(); 11 t.add(new Unicorn(2,"huahua")); 12 t.add(new Unicorn(1,"tete")); 13 t.add(new Unicorn(1,"meme")); 14 //遍歷集合 15 Iterator<Unicorn> it = t.iterator(); 16 while(it.hasNext()){ 17 Unicorn u = it.next(); 18 System.out.println(u.getAge() + " " + u.getName()); 19 } 20 } 21 } 22 23 class Unicorn implements Comparable<Unicorn>{ 24 private int age; 25 private String name; 26 27 public Unicorn(int age, String name) { 28 this.age = age; 29 this.name = name; 30 } 31 32 public int getAge() { 33 return age; 34 } 35 36 public void setAge(int age) { 37 this.age = age; 38 } 39 40 public String getName() { 41 return name; 42 } 43 44 public void setName(String name) { 45 this.name = name; 46 } 47 48 @Override 49 public int compareTo(Unicorn u) { 50 int temp = this.age - u.age; 51 return temp == 0 ? this.name.compareTo(u.name):temp; 52 } 53 }
4、泛型的不一樣的使用場景
1.泛型類或接口:表示該類或接口之後要操做的引用類型不肯定,因此在定義的時候須要定義爲泛型類或接口。
在建立對象的時候,指定具體要操做的類型。類/接口<參數類型>
2.泛型方法:表示該方法之後要操做的引用類型不肯定,因此在定義的時候定義爲泛型方法,注意:泛型方法的
定義與其所在的類或接口是否爲泛型類或接口沒有關係。靜態方法因爲不能訪問泛型類的類型參數,因此假如該靜態
方法須要使用泛型,則將該方法定義爲泛型方法。泛型方法的調用與普通方法沒有區別。<參數類型> 返回值
5、泛型的高級應用
1.泛型通配符:?表示,一般用於操做任意參數類型的泛型。強調的是通用性。
2.泛型的界限:其目的是在必定範圍內擴大能夠操做的參數類型。分爲上界限,和下界限。
泛型上界:表現形式:<? extends A> 表示的含義是:能夠操做的參數類型能夠是,A類型以及A的子類。一般這種
在集合中取出元素的時候經常使用,一般用A類型來接收取出的元素。<=A
泛型下界:表現形式:<? super A> 表示的含義是:能夠操做的參數類型是:A類型及其父類型。一般這種在接收元素
作比較的時候使用,能夠使用本身的比較器,也能夠使用父類的比較器。泛型下限的使用很少 。>=A
注意:ArrayList<Animal> list = new ArrayList<Cat>(); 這是錯誤的兩邊的泛型類型不匹配。
ArrayList<? extends Animal> list = new ArrayList<Cat>(); 這樣纔是正確的寫法,泛型匹配。
1 /*定義泛型類,泛型接口,泛型方法 2 *注意:既然使用泛型,就表示操做的類型不肯定,一般能夠調用的 3 *方法都是公共的方法,從Object裏繼承獲得的方法。 4 * */ 5 public class Tool<T> { 6 private T t; 7 8 public T getT() { 9 return t; 10 } 11 12 public void setT(T t) { 13 this.t = t; 14 } 15 16 public void print(T t){ 17 System.out.println("print " + t.toString()); 18 } 19 public static <Y> void method(Y y){ 20 System.out.println("method " + y.toString()); 21 } 22 }
1 /*泛型接口:要麼在具體類實現的時候定義參數類型或在建立子類對象的時候明確參數類型 2 *這是根據何時能夠明確操做的類型肯定的。 3 * */ 4 public interface GenericsInter<T> { 5 void method(T t); 6 } 7 8 class A implements GenericsInter<String>{ 9 @Override 10 public void method(String t) { 11 // TODO Auto-generated method stub 12 13 } 14 } 15 16 class B<T> implements GenericsInter<T>{ 17 @Override 18 public void method(T t) { 19 // TODO Auto-generated method stub 20 21 } 22 }
1 import java.util.*; 2 3 /*使用泛型的通配符,泛型上界限*/ 4 public class GenericsBound { 5 public static void main(String[] args) { 6 ArrayList<Personn> list1 = new ArrayList<Personn>(); 7 list1.add(new Personn(23, "hehe")); 8 list1.add(new Personn(34, "nini")); 9 ArrayList<Student> list2 = new ArrayList<Student>(); 10 list2.add(new Student(13,"keke")); 11 list2.add(new Student(19,"oo")); 12 ArrayList<Integer> list3 = new ArrayList<Integer>(); 13 list3.add(9); 14 list3.add(4); 15 printCollection(list1); 16 printCollection(list2); 17 printCollection(list3); 18 printCollection1(list1); 19 printCollection1(list2); 20 //printCollection1(list3);---限定了因此不能夠傳入該參數 21 } 22 23 //使用的泛型通配符能夠操做泛型參數類型是任意的 24 public static void printCollection(Collection<?> c){ 25 Iterator<?> it = c.iterator(); 26 while(it.hasNext()){ 27 System.out.println(it.next().toString()); 28 } 29 } 30 //只接收泛型參數類型是Personn及其子類的集合 31 public static void printCollection1(Collection<? extends Personn> c){ 32 Iterator<? extends Personn> it = c.iterator(); 33 while(it.hasNext()){ 34 System.out.println(it.next().toString()); 35 } 36 } 37 38 } 39 40 class Personn{ 41 private int age; 42 private String name; 43 44 public Personn(int age, String name) { 45 this.age = age; 46 this.name = name; 47 } 48 public int getAge() { 49 return age; 50 } 51 public void setAge(int age) { 52 this.age = age; 53 } 54 public String getName() { 55 return name; 56 } 57 public void setName(String name) { 58 this.name = name; 59 } 60 61 public String toString(){ 62 return "person " + getName() + " " + getAge(); 63 } 64 65 } 66 67 class Student extends Personn{ 68 69 public Student(int age, String name) { 70 super(age, name); 71 } 72 public String toString(){ 73 return "student " + getName() + " " + getAge(); 74 } 75 } 76 77 class Worker extends Personn { 78 79 public Worker(int age, String name) { 80 super(age, name); 81 } 82 83 public String toString(){ 84 return "worker " + getName() + " " + getAge(); 85 } 86 }
1 public static void printCollection3(Collection<? super Student> c){ 2 Iterator<? super Student> it = c.iterator(); 3 while(it.hasNext()){ 4 System.out.println(it.next().toString()); 5 } 6}
泛型下界限:此時只能打印參數類型爲Student類型及其父類類型的集合
1 import java.util.Comparator; 2 import java.util.TreeSet; 3 /*泛型下界限的使用 4 *TreeSet(Comparator<? super E>) 對於元素E類型能夠使用本身的比較器或者父類的比較器*/ 5 public class Generic_LowBound { 6 public static void main(String[] args) { 7 TreeSet<Student> t1 = new TreeSet<Student>(new ComparateByPersonn()); 8 t1.add(new Student(12,"hyhy")); 9 t1.add(new Student(14,"uiui")); 10 System.out.println(t1); 11 TreeSet<Student> t2 = new TreeSet<Student>(new ComparateByStudent()); 12 t2.add(new Student(12,"hyhy")); 13 t2.add(new Student(14,"uiui")); 14 System.out.println(t2); 15 } 16 } 17 18 class ComparateByPersonn implements Comparator<Personn>{ 19 @Override 20 public int compare(Personn o1, Personn o2) { 21 int temp = o1.getName().compareTo(o2.getName()); 22 return temp == 0 ? (o1.getAge() -o2.getAge()) :temp; 23 } 24 } 25 26 class ComparateByStudent implements Comparator<Student>{ 27 @Override 28 public int compare(Student o1, Student o2) { 29 int temp = o1.getName().compareTo(o2.getName()); 30 return temp == 0 ? (o1.getAge() -o2.getAge()) :temp; 31 } 32 } 33 34 class ComparateByWorker implements Comparator<Worker>{ 35 public int compare(Worker o1, Worker o2) { 36 int temp = o1.getName().compareTo(o2.getName()); 37 return temp == 0 ? (o1.getAge() -o2.getAge()) :temp; 38 } 39 }