首页 > 代码库 > Java之泛型

Java之泛型

1. 概述
          在引入泛型之前,Java类型分为原始类型、复杂类型,其中复杂类型分为数组和类。引入泛型后,一个复杂类型就可以在细分成更多的类型。
          例如原先的类型List,现在在细分成List<Object>, List<String>等更多的类型。
          注意,现在List<Object>, List<String>是两种不同的类型,他们之间没有继承关系,即使String继承了Object。下面的代码是非法的:

1 List<String> ls = new ArrayList<String>();
2 List<Object> lo = ls;

         这样设计的原因在于,根据lo的声明,编译器允许你向lo中添加任意对象(例如Integer),但是此对象是List<String>,破坏了数据类型的完整性。
         在引入范型之前,要在类中的方法支持多个数据类型,就需要对方法进行重载,在引入范型后,可以解决此问题(多态),更进一步可以定义多个参数以及返回值之间的关系。例如:

1 public void write(Integer i, Integer[] ia);
2 public void write(Double  d, Double[] da);

的范型版本为:

1 public <T> void write(T t, T[] ta);

在看下面代码:

 1 public class GenericTest {
 2 
 3     public static void main(String[] args) {
 4         List list = new ArrayList();
 5         list.add("qqyumidi");
 6         list.add("corn");
 7         list.add(100);
 8 
 9         for (int i = 0; i < list.size(); i++) {
10             String name = (String) list.get(i); // 1
11             System.out.println("name:" + name);
12         }
13     }
14 }

      定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于//1中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。

通过使用泛型,解决上面异常,修改代码如下:

 1 public class GenericTest {
 2 
 3     public static void main(String[] args) {
 4         /*
 5         List list = new ArrayList();
 6         list.add("qqyumidi");
 7         list.add("corn");
 8         list.add(100);
 9         */
10 
11         List<String> list = new ArrayList<String>();
12         list.add("qqyumidi");
13         list.add("corn");
14         //list.add(100);   // 1  提示编译错误
15 
16         for (int i = 0; i < list.size(); i++) {
17             String name = list.get(i); // 2
18             System.out.println("name:" + name);
19         }
20     }
21 }

总结: 使用泛型可以指代任意对象类型,定义的容器所放的内容是一个统一的类型;   

java中泛型的引入主要是为了解决两个方面的问题:
1. 集合类型元素在运行期出现类型装换异常,引入泛型增加编译时类型的检查;(即:消除强制类型转换,提高 Java 程序的类型安全)
2. 解决开发时重复代码的编写,能够复用算法。(比如:在类中的方法支持多个数据类型,就需要对方法进行重载)

 

 

2. 定义泛型类

我们直接上代码:

 1 package com.learn.chap06.sec01;
 2 
 3 public class Fdemo<T> {  // 泛型类
 4     private T a;
 5 
 6     public Fdemo(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("Obeject类型为:"+a.getClass().getName());
21     }
22     
23     
24 }
 1 package com.learn.chap06.sec01;
 2 /**
 3  * 定义泛型类    (使用泛型可以指代任意对象类型)
 4  * @author Administrator
 5  *
 6  */
 7 public class Fdemotest {
 8     
 9     public static void main(String[] args) {
10         Fdemo<Integer> test = new Fdemo<Integer>(12);
11         test.print();
12         System.out.println("test="+test.getA());
13         
14         Fdemo<String> strFdemo = new Fdemo<String>("我是中国人");
15         strFdemo.print();
16         System.out.println("strFdemo="+strFdemo.getA());
17     }
18 }

运行结果:

Obeject类型为:java.lang.Integer
test=12
Obeject类型为:java.lang.String
strFdemo=我是中国人

 

3. 限制泛型:

我们直接上代码:

1 package com.learn.chap06.sec02;
2 
3 public class Animal {
4     public void say() {
5         System.out.println("它是动物");
6     }
7 }
 1 package com.learn.chap06.sec02;
 2 
 3 public class Dog extends Animal{
 4 
 5     @Override
 6     public void say() {
 7         // TODO Auto-generated method stub
 8         System.out.println("它是一只狗");
 9     }
10     
11     
12 }
 1 package com.learn.chap06.sec02;
 2 
 3 public class Cat extends Animal{
 4 
 5     @Override
 6     public void say() {
 7         // TODO Auto-generated method stub
 8         System.out.println("它是一只猫");
 9     }
10     
11     
12 }
 1 package com.learn.chap06.sec02;
 2 
 3 public class Demo<T extends Animal>{
 4     private T ob;
 5 
 6     public Demo(T ob) {
 7         super();
 8         this.ob = ob;
 9     }
10 
11     public T getOb() {
12         return ob;
13     }
14 
15     public void setOb(T ob) {
16         this.ob = ob;
17     }
18     
19     public void print(){
20         System.out.println("T的类型是:"+ob.getClass().getName());
21     }
22 }
 1 package com.learn.chap06.sec02;
 2 /**
 3  * 限制泛型
 4  * @author Administrator
 5  *
 6  */
 7 public class Test {
 8     public static void main(String[] args) {
 9         Demo<Dog> demo = new Demo<Dog>(new Dog());
10         //demo.say(); 
11         demo.print();
12         
13         //Demo<Integer> demo = new Demo<Integer>(new Dog()); // 由于泛型定义Demo类的类型必须为Animal或其子类Dog和Cat,而Integer不是Animal的子类,所以类型被限制,即:限制泛型,导致编译报错
14         Demo<Animal> demo2 = new Demo<Animal>(new Cat());
15         demo2.print();
16         
17         Demo<Cat> demo3 = new Demo<Cat>(new Cat());
18         demo3.print();
19         
20     }
21 }

运行结果:

T的类型是:com.learn.chap06.sec02.Dog
T的类型是:com.learn.chap06.sec02.Cat
T的类型是:com.learn.chap06.sec02.Cat

 

4. 通配符泛型:

我们直接上代码:

 1 package com.learn.chap06.sec03;
 2 
 3 import com.learn.chap06.sec02.Animal;
 4 import com.learn.chap06.sec02.Cat;
 5 import com.learn.chap06.sec02.Demo;
 6 import com.learn.chap06.sec02.Dog;
 7 
 8 public class Test1 {
 9     /**
10      * 通配符泛型
11      * @param demo
12      */
13     public static void take(Demo<?> demo){ // <?> 即为:通配符泛型
14         demo.print();
15     }
16     
17     public static void main(String[] args) {
18         Demo<Dog> demo1 = new Demo<Dog>(new Dog());
19         take(demo1);
20         
21         Demo<Cat> demo2 = new Demo<Cat>(new Cat());
22         take(demo2);
23         
24         Demo<Animal> demo3 = new Demo<Animal>(new Animal());
25         take(demo3);
26     }
27 }

运行结果:

T的类型是:com.learn.chap06.sec02.Dog
T的类型是:com.learn.chap06.sec02.Cat
T的类型是:com.learn.chap06.sec02.Animal

 

5. 泛型方法:

 1 package com.learn.chap06.sec04;
 2 
 3 public class Test {
 4     
 5     /**
 6      * 泛型方法
 7      * @param t
 8      */
 9     public  static <T> void f(T t) {
10         System.out.println("T的类型是:"+t.getClass().getName());
11     }
12     
13     public static void main(String[] args) {
14         f(1);
15         f("hello");
16         f(1.0f);
17         f(new Object());
18     }
19 }

运行结果:

T的类型是:java.lang.Integer
T的类型是:java.lang.String
T的类型是:java.lang.Float
T的类型是:java.lang.Object

现在使用泛型没问题了吧!呵呵

 

Java之泛型