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

浙公网安备 33010602011771号