Java泛型

一、定义

    泛型可以用来指代任意对象类型。

 

二、泛型和多态

1.引入多态  

定义一个C1类:里面有个Integer属性,给出它的构造方法、打印其类型和get\set方法。

 1 package com.swu.generics;
 2 
 3 public class C1 {
 4     private Integer a;
 5 
 6     public C1(Integer a) {
 7         super();
 8         this.a = a;
 9     }
10 
11     public Integer getA() {
12         return a;
13     }
14 
15     public void setA(Integer a) {
16         this.a = a;
17     }
18     
19     
20     /**
21      * 打印a的类型
22      */
23     public void print() {
24         System.out.println("a的类型是:" + a.getClass().getName());
25     }
26 }

  同理定义一个C2类,里面定义一个String属性:

 1 package com.swu.generics;
 2 
 3 public class C2 {
 4     private String a;
 5 
 6     public C2(String a) {
 7         super();
 8         this.a = a;
 9     }
10 
11     public String getA() {
12         return a;
13     }
14 
15     public void setA(String a) {
16         this.a = a;
17     }
18     
19     /**
20      * 打印a的类型
21      */
22     public void print() {
23         System.out.println("a的类型是:" + a.getClass().getName());
24     }
25 }

 写个Test1类用于测试:

 1 package com.swu.generics;
 2 
 3 public class Test1 {
 4 
 5     public static void main(String[] args) {
 6         //begin test C1
 7         C1 c1 = new C1(1);
 8         c1.print();
 9         int i1 = c1.getA();
10         System.out.println("i1 = " + i1);
11         //end test C1
12         
13         //begin test C2
14         C2 c2 = new C2("I'm C2");
15         c2.print();
16         String i2 = c2.getA();
17         System.out.println(i2);
18         //end test C2
19         
20     }
21 
22 }

输出结果:

假如有其他类型,我们就要写很多C3、C4......很麻烦,这个时候我们想起用多态。对以上代码进行改写:

 

2.用多态进行改写

将上述C1、C2用一个类实现,因为所有的类都继承自Object类,所以直接定义Object类型的属性:

 1 package com.swu.generics;
 2 
 3 public class C12 {
 4     private Object a;
 5 
 6     public C12(Object a) {
 7         super();
 8         this.a = a;
 9     }
10 
11     public Object getA() {
12         return a;
13     }
14 
15     public void setA(Object a) {
16         this.a = a;
17     }
18     
19     /**
20      * 打印a的类型
21      */
22     public void print() {
23         System.out.println("a的类型是:" + a.getClass().getName());
24     }
25 }

写下测试类:

 1 package com.swu.generics;
 2 
 3 public class Test1 {
 4 
 5     public static void main(String[] args) {
 6         //begin test C1
 7         C1 c1 = new C1(1);
 8         c1.print();
 9         int i1 = c1.getA();
10         System.out.println("i1 = " + i1);
11         //end test C1
12         
13         //begin test C2
14         C2 c2 = new C2("I'm C2");
15         c2.print();
16         String i2 = c2.getA();
17         System.out.println("i2:" + i2);
18         //end test C2
19         
20         //begin test C12
21         C12 c12 = new C12(12);//向上转型  int->Object 不会出错
22         c12.print();
23         int i3 = (int)c12.getA();//向下转型 Object->int 会出错
24         System.out.println("i3:" + i3);
25         
26         C12 c122 = new C12("I am C122");
27         c122.print();
28         String i4 = (String)c122.getA();
29         System.out.println("i4:" + i4);
30         //end test C12
31     }
32 
33 }

测试结果:

使用多态我们可以让类简单,但是具体实现仍然没有简化,需要向上向下转型,容易出错。而泛型就是既可以简化类,也可以简化实现的方法。

 

3.使用泛型

先定义一个泛型类:

 1 package com.swu.generics;
 2 
 3 /**
 4  * 泛型类
 5  * @author 健泽
 6  * @param <T> T可以用其他字母代替
 7  */
 8 public class CC<T> {
 9     private T a;
10     
11     public CC(T a) {
12         super();
13         this.a = a;
14     }
15     
16     public T getA() {
17         return a;
18     }
19 
20     public void setA(T a) {
21         this.a = a;
22     }
23     
24     /**
25      * 打印a的类型
26      */
27     public void print() {
28         System.out.println("a的类型是:" + a.getClass().getName());
29     }
30 }

再进行测试:

 1 package com.swu.generics;
 2 
 3 public class Test1 {
 4 
 5     public static void main(String[] args) {
 6         //begin test C1
 7         C1 c1 = new C1(1);
 8         c1.print();
 9         int i1 = c1.getA();
10         System.out.println("i1 = " + i1);
11         //end test C1
12         
13         //begin test C2
14         C2 c2 = new C2("I'm C2");
15         c2.print();
16         String i2 = c2.getA();
17         System.out.println("i2:" + i2);
18         //end test C2
19         
20         //begin test C12
21         C12 c12 = new C12(12);//向上转型  int->Object 不会出错
22         c12.print();
23         int i3 = (int)c12.getA();//向下转型 Object->int 会出错
24         System.out.println("i3:" + i3);
25         
26         C12 c122 = new C12("I am C122");
27         c122.print();
28         String i4 = (String)c122.getA();
29         System.out.println("i4:" + i4);
30         //end test C12
31         
32         //begin test CC
33         CC<Integer> cc = new CC<Integer>(1222);//泛型实例化方式
34         cc.print();
35         int i5 = cc.getA();
36         System.out.println("i5:" + i5);
37         
38         CC<String> cc1 = new CC<String>("I am generics and I am easy.");
39         cc1.print();
40         String i6 = cc1.getA();
41         System.out.println("i6:" + i6);
42         //end test cc
43     }
44 
45 }

测试结果:

可以看到,使用泛型在实例化的时候就确定了类型,避免了转型麻烦,更加简单。注意泛型实例化的方式

 

三、限制泛型类型

前面我们说的泛型,可以是任意类型,但是有时候我们需要限制类型,这样更加安全。

我们通过实例理解,新建一个Animal类,再建两个子类Dog类和Cat类:

1 package com.swu.generics02;
2 
3 public class Animal {
4     public void print() {
5         System.out.println("Animal");
6     }
7 }
1 package com.swu.generics02;
2 
3 public class Dog extends Animal {
4     public void print() {
5         System.out.println("Dog");
6     }
7 }
1 package com.swu.generics02;
2 
3 public class Cat extends Animal{
4     public void print() {
5         System.out.println("Cat");
6     }
7 }

然后再定义一个泛型类:

 1 package com.swu.generics02;
 2 
 3 public class Demo <T extends Animal>{
 4     private T a;
 5 
 6     public Demo(T a) {
 7         super();
 8         this.a = a;
 9     }
10 
11     public T getA() {
12         return a;
13     }
14 
15     public void setA(T a) {
16         this.a = a;
17     }
18     
19     public void print() {
20         System.out.println("a的类型是:" + a.getClass().getName());
21     }
22 }

这里对泛型类进行了限制,必须是Animal类或者是Animal的子类。

新建一个测试类:

 1 package com.swu.generics02;
 2 
 3 public class Test {
 4     public static void main(String[] args) {
 5         Demo<Dog> dd = new Demo<Dog>(new Dog());
 6         Dog dog = dd.getA();
 7         dog.print();
 8         
 9         Demo<Cat> dc = new Demo<Cat>(new Cat());
10         Cat cat = dc.getA();
11         cat.print();
12         
13         Demo<Animal> ad = new Demo<Animal>(new Animal());
14         ad.print();
15         
16     }
17 }

输出如下:

 

如果Demo<Animal>中将Animal换成其他类就会报错,类型不匹配:

 

四、通配符泛型

通配符泛型在使用泛型特殊的场景下用到,比如把泛型对象作为方法参数传入方法的时候,就用到通配符泛型。在调用该方法时,要将具体的对象作为参数传入。

 1 package com.swu.generics02;
 2 
 3 public class Test {
 4     /**
 5      * 通配符泛型 具体使用方法时,用具体类型代替?
 6      * @param demo
 7      */
 8     public static void take(Demo<?> demo) {
 9         demo.print();
10     }
11     
12     public static void main(String[] args) {
13         Demo<Dog> dg = new Demo<Dog>(new Dog());
14         take(dg);
15         
16         Demo<Cat> dc = new Demo<Cat>(new Cat());
17         take(dc);
18         
19         Demo<Animal> da = new Demo<Animal>(new Animal());
20         take(da);
21     }
22 }

输出:

 

 

五、泛型方法

泛型方法是指返回值和参数都用泛型表示的方法,其中返回类型可以是int、void、T等。

 1 package com.swu.generics02;
 2   
 3 public class Test2 {
 4     
 5     /**
 6      * 泛型方法
 7      * @param <T> 声明T 否则参数不知道T是什么
 8      * @param t 泛型参数
 9      */
10     public static <T> void getClass(T t){
11         System.out.println("类型是" + t.getClass().getName());
12     }
13     
14     public static void main(String[] args) {
15         getClass(1);
16         getClass("ad");
17         getClass(1.02);
18         getClass(new Object());
19     }
20 }

输出:

 

 

posted @ 2020-05-30 22:11  健泽  阅读(342)  评论(0编辑  收藏  举报