一、泛型的引入原因
在操作集合的時候,之前方法的定義都是Object類型,向集合中添加對象,都自動向上轉型,加入的元素可以是任何類型
但是,在取出元素的時候,通常想要使用對象的特有功能,就必須向下轉型,此時就可能出現類型轉換異常,存在安全隐患。
在JDK1.5時候提出一個解決方案:泛型。
二、泛型的定義及好處
泛型:是一種應用在編譯時期的安全機制,具體的做法:有點類似于數組的思想,定義操作的時候,指定好要操作的類型資訊
eg:ArrayList<String>:表示該ArrayList隻能操作字元串類型的元素,假如要向其中添加Integer類型,就會編譯失敗。
<>尖括号中指定被操縱的對象的類型。
好處:将運作期間可能出現的異常,轉化為編譯時期的強制檢驗,避免了強制類型轉換;也提供了設計上的便捷
三、泛型的擦除和補償
泛型擦除:具體指的是編譯器在堆源代碼進行完類型檢查後,在生成位元組碼檔案的時候,會濾過泛型指定的類型資訊,是以
生成的位元組碼檔案中不含有具體的類型資訊--變為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 }
四、泛型的不同的使用場景
1.泛型類或接口:表示該類或接口以後要操作的引用類型不确定,是以在定義的時候需要定義為泛型類或接口。
在建立對象的時候,指定具體要操作的類型。類/接口<參數類型>
2.泛型方法:表示該方法以後要操作的引用類型不确定,是以在定義的時候定義為泛型方法,注意:泛型方法的
定義與其所在的類或接口是否為泛型類或接口沒有關系。靜态方法由于不能通路泛型類的類型參數,是以假如該靜态
方法需要使用泛型,則将該方法定義為泛型方法。泛型方法的調用與普通方法沒有差別。<參數類型> 傳回值
五、泛型的進階應用
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 }