Java泛型设计

Java中的泛型(genericity)设计实际上和C++中的模板设计是一种概念

下面介绍java当中的几种泛型

1、 泛型类和泛型接口

   ①定义格式:只是在定义类或接口时,在类名或接口名后面加上

               <类型参数1,类型参数2,类型参数3,.......>

              即可      ②这里的类型参数的个数是任意的,根据实际需要进行设定

     类型参数的定义形式有三种:

      <1> 类型变量标示符   

      <2> 类型变量标示符 extends 父类型

      <3> 类型变量标示符 extends 父类型1 & 父类型2 &.....& 父类型n

      分析:1.<1>方式 即可以以任意的合法的标示符作为类型变量

               如 class Point<T>

                  {....}

            2.<2>方式 即 class Point<T extends java.lang.Number>{.....}

              这就是说对T做了一个限定,限定T只能是java.lang.Number类的一个

              子类类型,不能是其他类型,再实例化Point类的对象时,就必须用一个

              Number类的子类实例化这个泛型类;对于<1>实际上是默认

               T extends java.lang.Object

              所以<1>方式当中的类型变量标示符T 可以用任意一个实例对象对之进行实例化

           3. <3>方式 即 class Point<T extends java.lang.Number & 接口名1 & 接口名2>

              我们要强调一下,在类的继承和实现接口的规则当中如果是继承则使用extends关键字

              ,实现某个接口使用implements;但是在受限泛型当中只有extends关键字,

              extends后面的父类型不仅可以是某个类,还可以是某个接口,都用extends关键字

              不用implements,即是说"父类型"只是个宽泛的概念;

           4.如果使用了方式<3>,那么就指出了T同时具有所有父类(包括接口)

              的功能,但是java中规定,类是不能多继承的,那么我们应该用什么样的实例对象

              来实例化这个泛型呢?只能如下:                 

              ① 程序当中有一个类,他同时实现了许多接口;

                  这些接口就是"父类型",那么这个类就可以实例化这个泛型了,因为他确实

                  同时具有所有"父类型"的功能

               ② 程序当中有一个类,他继承了某一个类,并同时继承了多个接口

                  同理这个类拥有了这个父类和所有接口的功能,顾可以用来实例化泛型

            5.通过上面的分析可知,方式<3>中的"父类型",最多只能有一个类,其他的都是接口

              或者全是接口

2、泛型方法

   ①实际上不仅一个类能够使用泛型技术,一个方法同样可以单独使用泛型技术成为泛型方法

     一个泛型方法的定义只需要在该方法的返回值的前面加上 <类型参数1,类型参数2....>

     其中这些类型参数应遵守和泛型类中一样的规则

   ②需要注意的是,泛型方法必须通过引用型变量进行调用,即使是在同一个类的内部也要用

     this.<Double>f(); 来调用,不能直接写<Double>f();当类型参数只使用在类方法的参数列表

     当中,那么程序就能够自动根据实参判定类型参数的实际意义,所以当调用方法时就不用再

     明确指出<Double>了  

   ③在JDK 5.0 开始,允许使用可变参数泛型方法,当时要求可变参数的类型参数变量要在方法的

     参数列表的最后面

       public <T extends java.lang.Number> void function(String str, T...args)

       {.....}

       T...args在参数列表的最后

3、通配符和受限通配符在泛型设计当中的使用

   ① 正如上面所说的,如果使用泛型的话,会有下面的情况:

      public class Generics<T>            

      {          

          private T obj ;

          public void setObj(T obj)

          { this.obj = obj ; }

          public T getObj()            

         { return obj ;}             

      }

     Generics<ArrayList> gen1 = new Generics<ArrayList>();

     Generics<LinkedList>gen2 = new Generics<LinkedList>();

     也就是说,gen1与gen2都只能指向单独的一种实例化的泛型

   ② java中的通配符"?"就可以实现下面这种情况

      Generics<? extends List> gen = null ;

      gen = gen1 ;

      System.out.println(gen.getObj());

      gen = gen2 ;

      System.out.println(gen.getObj());

      即<? extends List>这个语段就规定了,引用型变量gen可以指向 所有List类或者其子类

      实例化的泛型对象

   ③ 通配符只是用在声明引用型变量的语句当中,在定义泛型时不会用到通配符

      <?> 默认的是<? extends java.lang.Object>

      <? extends SomeClass> 即声明的引用型变量必须是指向 SomeClass类或者是其子类

                            实例化的泛型对象

      <? super SomeClass> 即声明的引用型变量必须指向 SomeClass类或者是其父类

                            实例化的泛型对象

   ④ 还有一点值得非常注意,那就是说

      所有使用<?>或<? extends SomeClass>方式声明的引用型的变量gen,通过gen只能够

      获取实例泛型对象的信息,或者是的说用null移除实例泛型对象的某些信息

      但是不能够通过gen调用那些设置实例泛型对象信息的方法来设定信息,

      即不能够增加实例泛型对象的

      信息         如:             

       Generics<String> gen = new Generics<String>() ;

       gen.setObj("cat");

       Generics<?>gen2 = gen ;         

        System.out.println(gen2.getObj()) ;  //正确,可以获取gen对象的信息

       gen2.setObj(null);    //正确,可以移除gen对象中的信息                                       

       gen2.setObj("dog");  //报错,不能够通过gen2设置新的信息给gen

 

 

 

  

posted @ 2014-08-10 21:29  RoperLee  阅读(397)  评论(0)    收藏  举报