一、定义
泛型可以用来指代任意对象类型。
二、泛型和多态
1.引入多态
定义一个C1类:里面有个Integer属性,给出它的构造方法、打印其类型和get\set方法。
1 packagecom.swu.generics;2
3 public classC1 {4 privateInteger a;5
6 publicC1(Integer a) {7 super();8 this.a =a;9 }10
11 publicInteger getA() {12 returna;13 }14
15 public voidsetA(Integer a) {16 this.a =a;17 }18
19
20 /**
21 * 打印a的类型22 */
23 public voidprint() {24 System.out.println("a的类型是:" +a.getClass().getName());25 }26 }
同理定义一个C2类,里面定义一个String属性:
1 packagecom.swu.generics;2
3 public classC2 {4 privateString a;5
6 publicC2(String a) {7 super();8 this.a =a;9 }10
11 publicString getA() {12 returna;13 }14
15 public voidsetA(String a) {16 this.a =a;17 }18
19 /**
20 * 打印a的类型21 */
22 public voidprint() {23 System.out.println("a的类型是:" +a.getClass().getName());24 }25 }
写个Test1类用于测试:
1 packagecom.swu.generics;2
3 public classTest1 {4
5 public static voidmain(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 C112
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 packagecom.swu.generics;2
3 public classC12 {4 privateObject a;5
6 publicC12(Object a) {7 super();8 this.a =a;9 }10
11 publicObject getA() {12 returna;13 }14
15 public voidsetA(Object a) {16 this.a =a;17 }18
19 /**
20 * 打印a的类型21 */
22 public voidprint() {23 System.out.println("a的类型是:" +a.getClass().getName());24 }25 }
写下测试类:
1 packagecom.swu.generics;2
3 public classTest1 {4
5 public static voidmain(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 C112
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 C219
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 packagecom.swu.generics;2
3 /**
4 * 泛型类5 *@author健泽6 *@param T可以用其他字母代替7 */
8 public class CC{9 privateT a;10
11 publicCC(T a) {12 super();13 this.a =a;14 }15
16 publicT getA() {17 returna;18 }19
20 public voidsetA(T a) {21 this.a =a;22 }23
24 /**
25 * 打印a的类型26 */
27 public voidprint() {28 System.out.println("a的类型是:" +a.getClass().getName());29 }30 }
再进行测试:
1 packagecom.swu.generics;2
3 public classTest1 {4
5 public static voidmain(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 C112
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 C219
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 C1231
32 //begin test CC
33 CC cc = new CC(1222);//泛型实例化方式34 cc.print();35 int i5 =cc.getA();36 System.out.println("i5:" +i5);37
38 CC cc1 = new CC("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 packagecom.swu.generics02;2
3 public classAnimal {4 public voidprint() {5 System.out.println("Animal");6 }7 }
1 packagecom.swu.generics02;2
3 public class Dog extendsAnimal {4 public voidprint() {5 System.out.println("Dog");6 }7 }
1 packagecom.swu.generics02;2
3 public class Cat extendsAnimal{4 public voidprint() {5 System.out.println("Cat");6 }7 }
然后再定义一个泛型类:
1 packagecom.swu.generics02;2
3 public class Demo {4 privateT a;5
6 publicDemo(T a) {7 super();8 this.a =a;9 }10
11 publicT getA() {12 returna;13 }14
15 public voidsetA(T a) {16 this.a =a;17 }18
19 public voidprint() {20 System.out.println("a的类型是:" +a.getClass().getName());21 }22 }
这里对泛型类进行了限制,必须是Animal类或者是Animal的子类。
新建一个测试类:
1 packagecom.swu.generics02;2
3 public classTest {4 public static voidmain(String[] args) {5 Demo dd = new Demo(newDog());6 Dog dog =dd.getA();7 dog.print();8
9 Demo dc = new Demo(newCat());10 Cat cat =dc.getA();11 cat.print();12
13 Demo ad = new Demo(newAnimal());14 ad.print();15
16 }17 }
输出如下:
如果Demo中将Animal换成其他类就会报错,类型不匹配:
四、通配符泛型
通配符泛型在使用泛型特殊的场景下用到,比如把泛型对象作为方法参数传入方法的时候,就用到通配符泛型。在调用该方法时,要将具体的对象作为参数传入。
1 packagecom.swu.generics02;2
3 public classTest {4 /**
5 * 通配符泛型 具体使用方法时,用具体类型代替?6 *@paramdemo7 */
8 public static void take(Demo>demo) {9 demo.print();10 }11
12 public static voidmain(String[] args) {13 Demo dg = new Demo(newDog());14 take(dg);15
16 Demo dc = new Demo(newCat());17 take(dc);18
19 Demo da = new Demo(newAnimal());20 take(da);21 }22 }
输出:
五、泛型方法
泛型方法是指返回值和参数都用泛型表示的方法,其中返回类型可以是int、void、T等。
1 packagecom.swu.generics02;2
3 public classTest2 {4
5 /**
6 * 泛型方法7 *@param 声明T 否则参数不知道T是什么8 *@paramt 泛型参数9 */
10 public static voidgetClass(T t){11 System.out.println("类型是" +t.getClass().getName());12 }13
14 public static voidmain(String[] args) {15 getClass(1);16 getClass("ad");17 getClass(1.02);18 getClass(newObject());19 }20 }
输出: