第二步:学习泛型类的分类:
泛型在形式上是数据类型的抽象,这种数据类型可以是:
类范围的数据类型,也可以是方法范围的数据类型。
1. 类范围的泛型类型通常在类定义时进行声明,此泛型在整个类的范围内可以使用。
2. 方法范围的泛型类型在定义方法时进行声明,此泛型只能在方法的参数列表和返回数据类型上使用。
注:无论是类范围的泛型,还是方法级别的泛型变量,不经过任何限制,原则上只是一个占位符,没有太大的实用价值。泛型变量在使用时需要进行必要的限制。
第三步:类范围的泛型变量的限制
1.声明时使用extends关键字进行限制
在声明泛型变量时可以使用extends关键字限定泛型变量的上限。
<T extends Integer>中,泛型变量T可以是类Integer或Integer的子类。
<T extends InterfaceB>,则T可以是接口InterfaceB或实现了接口InterfaceB的类。
通过这种语法可以将泛型变量所指代的数据类型限制在某个范围内,便于在泛型类中针对泛型变量进行某些算法处理。
例子分析:
public class Calculator2 <MyType extends MyData>{
public void show(MyType a,MyType b){
a.show();
b.show();
}
}
interface MyData{
void show();
}
其泛型变量是一个实现或继承MyData接口的类,这里的extends不是继承之意,只是强调MyType在范围上小于等于MyData接口。
方法Show将两个MyType类型的参数分别进行显示,由于<MyType extends MyData>的定义已经限制了MyType的范围,所以类型MyType肯定具有show方法。
3. 使用通配符进行限制
泛型类在使用时必须用具体的数据类型对泛型变量进行替换,替换后的泛型类是一个具体类。但有时并不需要将泛型变量具体化,此时可以采用通配符”?”指代一种数据类型类型。
例:
public class MyClass2 {
public Calculator<?> function(Calculator<?>obj){
return obj;
}
}
上边的类Calculator<?>是一个范围十分广阔的泛型类。由于这种类型的类还是一种不完整的类,所以只能定义变量,不能构造对象。
public class TestMyClass2 {
public static void main(String args[]){
Calculator<Integer> obj = new Calculator<Integer>();
MyClass2 obj2 = new MyClass2();
Calculator<Integer>obj4 =(Calculator<Integer>)obj2.function(obj);//1
// Calculator<Integer>obj4 = obj2.function(obj);//2
Calculator<?>obj5 = obj2.function(obj);//3
int iResult= obj4.add(12, 13);
System.out.println(iResult);
}
}
注意:
1. 标记2处没有采用强制类型转换,且function(obj)返回的是一种Calculator<?>类型的数据,Calculator<Integer>是比该返回类型更窄的数据类型。因此会产生编译性错误。
2. 标记1处采用强制类型转换,所以编译器不会检查其合法性,所以要慎用。
3. 标记3处是可以接受的,可以用面向对象的多态来理解。
带有通配符的泛型类和java的抽象类十分相似,这种类型的变量可以引用范围内的所有对象,却不能直接用于构造对象。例:
Calculator<?> obj = Calculator<Integer>() 正确
Calculator<?> obj = Calculator<?>() 不正确
1. 使用关键字super进行限定(非声明时使用)
Super关键字通常用于限制泛型类型的下界。如:<T super Integer> 其中T可以是
Integer类型,也可以是Integer的所有父类,或者父类的父类。例:
public class PersonOP<MyType>{
public MyTypeshow(MyType a,MyType b){
return a;
}
}
class person{
public void show()
{
System.out.println("helloperson");
}
}
class student extends person
{
public void show()
{
System.out.println("hellostudent");
}
}
public class TestSupper {
public static void main(String args[]){
PersonOP<? super student>obj = new PersonOP<person>();
student p1 = new student();
p1.show();
obj.show(p1, p1);
}
}