限制泛型可用類型,類型通配符聲明,泛型方法,通配符聲明
一、限制泛型可用類型
① 在定義泛型類型時,默認在實例化泛型類的時候可以使用任何類型,但是如果想要限制使用泛型類型時,只能用某個特定類型或者是其子類型才能實例化該類型時,可以在定義類型時,使用extends關鍵字指定這個類型必須是繼承某個類,或者實現某個類;
② 當沒有指定泛型繼承的類型或接口時,默認使用extends Object,所以默認情況下任何類型都可以作為參數傳入;
繼承抽象類

![]()
1 public class GenericDemo3{
2 public static void main(String []args){
3 GenericClass<Dog> dogClass=new GenericClass<Dog>();
4 dogClass.setObj(new Dog());
5 dogClass.getObj().eat();
6
7
8 GenericClass<Cat> catClass=new GenericClass<Cat>();
9 catClass.setObj(new Cat());
10 catClass.getObj().eat();
11 }
12 }
13
14 //泛型類所接受的參數做了限制,只能接收Animal類型或者Animal類的子類
15 class GenericClass<T extends Animal>{
16 private T obj;
17 public void setObj(T obj){
18 this.obj=obj;
19 }
20 public T getObj(){
21 return obj;
22 }
23 }
24
25 abstract class Animal{
26 public abstract void eat();
27 }
28
29 class Dog extends Animal{
30 public void eat(){
31 System.out.println("啃骨頭");
32 }
33 }
34 class Cat extends Animal{
35 public void eat(){
36 System.out.println("吃魚肉");
37 }
38 }
View Code
繼承接口

![]()
1 public class GenericDemo3{
2 public static void main(String []args){
3 GenericClass<Dog> dogClass=new GenericClass<Dog>();
4 dogClass.setObj(new Dog());
5 dogClass.getObj().eat2();
6
7
8 GenericClass<Cat> catClass=new GenericClass<Cat>();
9 catClass.setObj(new Cat());
10 catClass.getObj().eat2();
11 }
12 }
13
14 //泛型類所接受的參數做了限制,只能接收Animal類型或者Animal類的子類
15 class GenericClass<T extends Animal2>{
16 private T obj;
17 public void setObj(T obj){
18 this.obj=obj;
19 }
20 public T getObj(){
21 return obj;
22 }
23 }
24
25 interface Animal2{
26 public abstract void eat2();
27 }
28
29 class Dog implements Animal2{
30 public void eat2(){
31 System.out.println("啃骨頭2");
32 }
33 }
34 class Cat implements Animal2{
35 public void eat2(){
36 System.out.println("吃魚肉2");
37 }
38 }
View Code
二、類型通配符聲明
① 同一泛型類,如果實例化時給定的實際類型不同,則這些實例的類型是不兼容的,不能相互賦值;
Generic<Boolean> f1=new Generic<Boolean>();
Generic<Integer> f2=new Generic<Integer>();
f1=f2;//發生編譯錯誤
Generic<Object> f=f1;//f1和f類型並不兼容,發生編譯錯誤
f=f2;//f2和f類型同樣不兼容,也會發生編譯錯誤
② 泛型類實例之間的不兼容性會帶來使用的不便。我們可以使用泛型通配符(?)聲明泛型類的變量就可以解決這個問題;
③ 泛型通配符的方式
“?”代表任意一個類型;
Generic<Boolean> f1=new Generic<Boolean>();
Generic<?> f=f1;
和限制泛型的上限相似,同樣可以使用extends關鍵字限定通配符匹配類型的上限;
Generic<Dog> f1=new Generic<Dog>();
Generic<? extends Animal> f=f1;
還可以使用super關鍵字將通配符類型限定為某個類型及其父類型;
Generic<Animal> f1=new Generic<Animal>();
Generic<? super Dog> f=f1;

![]()
1 public class GenericDemo4{
2 public static void main(String []args){
3 GenericClass<Dog> dogClass=new GenericClass<Dog>();
4 dogClass.setObj(new Dog());
5 dogClass.getObj().eat();
6
7 GenericClass<Cat> catClass=new GenericClass<Cat>();
8 catClass.setObj(new Cat());
9 catClass.getObj().eat();
10
11 GenericClass<String> StringClass=new GenericClass<String>();
12
13 //dogClass=catClass;//編譯出錯
14
15 //無限定通配符的使用
16 GenericClass<?> gClass=null;
17 gClass=dogClass;
18 ((Dog)gClass.getObj()).eat();//因父類為object類型,所以要強制轉換
19
20 gClass=StringClass;
21
22 //上邊界限定通配符
23 GenericClass<? extends Animal> subclass=null;
24 subclass=dogClass; //Animal a=dog;
25 subclass.getObj().eat();
26
27 //下邊界限定通配符
28 GenericClass<? super Dog> sclass=null;
29 GenericClass<Animal> cClass=new GenericClass<Animal>();
30 //sclass=catClass; //編譯錯誤,類型不兼容
31 sclass=cClass;//可以通過編譯
32 }
33 }
34
35
36 class GenericClass<T>{
37 private T obj;
38 public void setObj(T obj){
39 this.obj=obj;
40 }
41 public T getObj(){
42 return obj;
43 }
44 }
45
46 interface Animal{
47 public abstract void eat();
48 }
49
50 class Dog implements Animal{
51 public void eat(){
52 System.out.println("啃骨頭");
53 }
54 }
55 class Cat implements Animal{
56 public void eat(){
57 System.out.println("吃魚肉");
58 }
59 }
View Code
三、泛型方法
① 不僅類可以聲明泛型,類中的方法也可以聲明僅用於自身的泛型,這種方法叫做泛型方法。其定義格式為:
訪問修飾符<泛型列表> 返回類型 方法名(參數列表){
實現代碼
}
② 在泛型列表中聲明的泛型,可用於該方法的返回類型聲明、參數類型聲明和方法代碼中的局部變量的類型聲明;
③ 類中其它方法不能使用當前方法聲明的泛型;
注:是否擁有泛型方法,與其所在的類是否泛型沒有關系。要定義泛型方法,只需將泛型參數列表置於返回值前;
④ 什麼時候使用 泛型方法,而不是泛型類?
添加類型約束只作用於一個方法的多個參數之間,而不涉及到類中的其它方法;
施加類型約束的方法為靜態方法,只能將其定義為泛型方法,因為靜態方法不能使用其所在類的類型參數;
1 public class GenericDemo5{
2 public static void main(String []args){
3 GenericClass2 gen=new GenericClass2();
4 gen.println("abc");
5 gen.println(true);
6 gen.println(10);
7 gen.println(10.5);
8 gen.println(new Dog());
9 gen.println(new Cat());
10 GenericClass2.print("哈哈");
11 }
12 }
13
14 class GenericClass2{
15 //泛型方法
16 public <T> void println(T content){
17 System.out.println(content);
18 }
19 //泛型方法的重載
20 public <T extends Animal> void println(T animal){
21 animal.eat();
22 }
23
24 public static <T> void print(T content){
25 System.out.println(content);
26 }
27 }
28
29 interface Animal{
30 public abstract void eat();
31 }
32
33 class Dog implements Animal{
34 public void eat(){
35 System.out.println("啃骨頭");
36 }
37 }
38 class Cat implements Animal{
39 public void eat(){
40 System.out.println("吃魚肉");
41 }
42 }