Java集合框架(三)之泛型详解

来源:互联网 发布:淘宝客源码下载 编辑:程序博客网 时间:2024/04/28 11:08


泛型(Generics

什么是泛型?泛型是在jdk1.5以后出现的新特性,用于解决安全问题,是一个类型安全机制。

泛型格式:通过<>来定义要操作的引用数据类型。

 

例如以下的例子:

import java.util.*;

class GenericsDemo

{

         publicstatic void main(String[] args)

         {

                   ArrayList<String>  list=new ArrayList<String>();

                   list.add("zhangsan");

                   list.add("lisi");

                   list.add("huangsan");

                   //list.add(newInteger(3));//会出编译时错误

 

                   for(Iterator<String>it=list.iterator();it.hasNext();){

                            Strings=it.next();

                            System.out.println(s);

                   }

         }

}

我们可以看到使用泛型有很多好处。

a)  将运行时期出现问题ClassCastException,转移到了编译时期。方便程序员解决问题。让运行时期问题减少,安全。

b)  避免了强制转换的麻烦。

 

什么时候使用泛型呢?是在使用java提供的API的一些对象时,只要见到<>就要定义泛型,通常在集合框架中很常见。<>就是用来接受类型的,当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。

 

自定义泛型

自定义泛型类

 

自定义泛型有什么好处呢?自定义泛型最大的好处就是扩展性好。我们看看如下的例子:

class GenericsTool<T>

{

         privateT t;

         publicT getObject(){

                   returnt;

         }

         publicvoid setObject(T t){

                   this.t=t;  

         }

}

class CustomGenericsDemo

{

         publicstatic void main(String[] args)

         {

                   /*

                   Objcet

                   */

                   ObjectToolot=new ObjectTool();

                   ot.setObject(newStudent());

                   Studentstu=(Student)ot.getObject();

 

                   /*

                   Generics,T也可以是Student

                   */

                   GenericsTool<Person>gt=new GenericsTool<Person>();

                   gt.setObject(newPerson());

                   Personp=gt.getObject();//不需要强制转换

         }

}

我们可以看出自定义泛型的可扩展性高。

我们什么时候自定义泛型类呢?当类中要操作的引用数据类型不确定时候,我们在jdk1.5前是个使用Object来完成扩展,现在呢我们使用泛型来完成扩展。

 

自定义泛型方法

我们要注意,泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所要操作的类型就固定的了。就是说我们在泛型类里传入的类型是什么类型,它的泛型方法就是什么类型。这也是泛型类的一个局限性。

 

那么为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。就是说泛型就只能在方法里有效,在调用方法时,可以任意传入不同类型对象。

例如:

class MethodGenericsDemo

{

         publicstatic void main(String[] args)

         {

                   MethodGenericsDemomd=new MethodGenericsDemo();

                   /*

                  可以传入任何类型

                   */

                   md.show("haha");

                   md.show(3);

                   md.show(true);

         }

 

         public<T> void show(T t){  //泛型方法

           System.out.println(t);

         }

}

 

静态方法泛型:我们注意静态方法不可以访问类上定义的泛型。如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。

静态方法格式:public static  <T> void method(){};

自定义泛型接口

泛型自定义在接口是怎样的呢?

interface Generics<T>

{

         publicvoid show(T t);

}

/*

第一种实现泛型接口类

*/

class InGenerics_1 implementsGenerics<String>

{

         publicvoid show(String s){

                   System.out.println(s);

         }

}

/*

第二种实现泛型接口类

*/

class InGenerics_2<T> implementsGenerics<T>

{

         publicvoid show(T t){

                   System.out.println(t);

         }

}

class InterfaceGenericsDemo

{

         publicstatic void main(String[] args)

         {

                   InGenerics_1ig1=new InGenerics_1();

       ig1.show("haha");

 

                   InGenerics_2<Integer>ig2=new InGenerics_2<Integer>();

                            ig2.show(4);

         }

}

 

泛型限定(Generics  Qualify

什么是泛型限定呢?泛型限定是使用通配符,也可以理解为占位符,是用来表示不确定的类型。格式:<?>

泛型总共有两种限定:

a)  上限:<? extendsE>,可以接收E类型或者是E类型的子类

b)  下限:<?super E>,可以接受E类型或者E的父类型。通常用的不多。

 

如以下关于上限的例子:

import java.util.*;

class UpGenericsQualifyDemo

{

         publicstatic void main(String[] args)

         {

                   ArrayListlist1=new ArrayList();

                   list1.add(newPerson("zhangsan"));

                   list1.add(newPerson("lisi"));

                   list1.add(newPerson("wangwu"));

                   println(list1);

       

                   System.out.println("-----------------------");

                   ArrayListlist2=new ArrayList();

                   list2.add(newStudent("zhangsan_1"));

                   list2.add(newStudent("lisi_1"));

                   list2.add(newStudent("wangwu_1"));

                   println(list2);

         }

 

         publicstatic void println(ArrayList<?extends Person> list){

             for(Iterator<? extends Person>it=list.iterator();it.hasNext();){

                            System.out.println(it.next().getName());

                   }

         }

}

class Person

{

         privateString name;

         Person(Stringname){

            this.name=name;

         }

         publicString getName(){

                   returnname;

          }

}

class Student extends Person

{

         Student(Stringname){

                   super(name);

         }

}

 

我们知道集合类中TreeSet的一个Comparator接口的定义是publicComparator<? superE>comparator()这样定义的,这个就是所谓的下限。现在我们就这个举下例子:

import java.util.*;

class DownGenericsQualifyDemo

{

         publicstatic void main(String[] args)

         {

                   TreeSetsset=new TreeSet(new MyCom());

                   sset.add(newStudent("sa3"));

                   sset.add(newStudent("sa1"));

                   sset.add(newStudent("sa5"));

                   sset.add(newStudent("sa2"));

       for(Iterator it=sset.iterator();it.hasNext();){

                            System.out.println(it.next());

                   }

                  

                   System.out.println("---------------");

                   TreeSetwset=new TreeSet(new MyCom());

                   wset.add(newStudent("wa3"));

                   wset.add(newStudent("wa1"));

                   wset.add(newStudent("wa5"));

                   wset.add(newStudent("wa2"));

       for(Iterator it=wset.iterator();it.hasNext();){

                            System.out.println(it.next());

                   }

 

                  

         }

}

 

class Person

{

         privateString name;

         Person(Stringname){

            this.name=name;

         }

         publicString getName(){

                   returnname;

          }

          public String toString(){

                   return"name:"+name;

          }

}

class Student extends Person 

{

         Student(Stringname){

                   super(name);

         }

}

class Worker extends Person

{

         Worker(Stringname){

                   super(name);

         }

}

class MyCom implements Comparator<Person> //传一个父类型

{

        public int compare(Personp1,Person p2){

                  return(p1.getName()).compareTo(p2.getName());

        }

}

 

我们看到,我们使用了泛型中的下限,我们就创建了一个自定义比较器comparator