java 泛型(一)

我们在学习java的继承规则时,已经知道任何需要父类型的地方,都可以被替换成子类型,现在我们有如下类的继承结构:

  1. // 子类Student可以转换成父类Person  
  2. Student student = new Student();  
  3. Person person = student;  

然而泛型机制规定如下的转换是错误的:

  1. // Erro: Type mismatch: cannot convert from Result<Student> to Result<Person>  
  2. Result<Studentre_student = new Result<Student>(new Student(), new Student());  
  3. Result<Personre_person = re_student;  

在泛型机制里无论S和T这两个类是什么关系,Result<S>和Result<T>是没有什么联系的。

我们假设上述的泛型转换是成功的,那么我们就可以通过re_person的引用,将Teacher类的相关信息设置到Result<Student> re_student这个对象中,这显然是不允许的。

 

(一) 通配符类型------上界通配符<? extends T>

为了解决泛型这种使用起来的不便性,java泛型的设计者们引入了通配符"?"

比如Result<? extends Person>表示任何泛型Result类型,它的类型参数是Person以及Person的子类,如Result<Student>。

我们将上述的泛型转换改为如下形式:

 

  1. // Result<? extends Person>是Result<Student>的父类型  
  2. Result<Studentre_student = new Result<Student>(new Student(), new Student());  
  3. Result<? extends Personre_person = re_student;  

这种形式的转换就是正确的,我们称<? extends Person>为上界通配符


然而使用上界通配符也带来了一些副作用:

我们看如下的代码:

 

  1. public static void main(String [] args){  
  2.     // Result<? extends Person>是Result<Student>的父类型  
  3.     Result<Student> re_student = new Result<Student>(new Student(), new Student());  
  4.     Result<? extends Person> re_person = re_student;  
  5.     Person person = re_person.getCode();  
  6.     //Error:The method setCode(capture#2-of ? extends Person) in the type Result<capture#2-of ? extends Person> is not   
  7.     //applicable for the arguments (Student)  
  8.     re_person.setCode(new Student);  
  9. }  

看起来域的访问器setCode()方法无法使用
re_person.setCode(new Student);// Error
Result<? extends Person>的方法看起来是如下这样的:

  1. extends Person getCode() {  
  2.     return code;  
  3. }  
  4.   
  5. void setCode(? extends Person code) {  
  6.     this.code = code;  
  7. }  


setCode的形参是? extends Person code,但是不知道具体是什么类型这样就无法传递特定的类型,也就无法调用setCode()方法了,毕竟通配符"?"不能匹配具体的任何类型。
而getCode()是能正常调用的,我们知道? extends Person代表的是Person的子类,这样我们就可以把get到的值转换成父类型Person。


(二) 通配符类型------下界通配符<? super T>

在上面中我们说,当使用上界通配符<? extends T>时,只能get数据而不能set数据;而下界通配符<? super T>刚好相反,当使用下界通配符时,只能set数据而不能get数据。

<? super Student> 表示将通配符限制为Student或者及其超类,如下图所示:


 

当使用Result<? super Student>下界通配符时,其方法看起来是这样的:

 

  1. super Student getCode() {  
  2.     return code;  
  3. }  
  4.   
  5. void setCode(? super Student code) {  
  6.     this.code = code;  
  7. }  

对于set操作我们已经知道形式参数是Student或者Student的超类
那么我们就可以使用小于等于Student粒度的类型来传递参数

对于get操作 我们只知道返回值是Student或者Student的超类 但具体是什么类型我们不知道 所有我们无法
给具体的类进行赋值;只能赋值给Object对象

 

  1. public static void main(String [] args){  
  2.     // Result<? super Student>为下界通配符  
  3.     Result<Student> re_student = new Result<Student>(new Student(), new Student());  
  4.     Result<? super Student> sre_student = re_student;  
  5.       
  6.     // Error:The method setCode(capture#4-of ? super Student) in the type Result<capture#4-of ? super Student> is not   
  7.     // applicable for the arguments (Person)  
  8.     sre_student.setCode(new Person());  
  9.       
  10.     // right operation  
  11.     // 对于set操作我们已经知道形式参数是Student或者Student的超类  
  12.     // 那么我们就可以使用小于等于Student粒度的类型来传递参数  
  13.     sre_student.setCode(new Graduate());  
  14.     sre_student.setCode(new Master());  
  15.       
  16.       
  17.     // Error:Type mismatch: cannot convert from capture#5-of ? super Student to Student  
  18.     // 对于get操作 我们只知道返回值是Student或者Student的超类 但具体是什么类型我们不知道 所有我们无法  
  19.     // 给具体的类进行赋值;只能赋值给Object对象  
  20.     Student student = sre_student.getCode();  
  21.       
  22.     // right operation  
  23.     Object object = sre_student.getCode();  
  24. }  


(三) 总结限定通配符的使用

<? extends T>:上界通配符 只能取数据而不能写入数据

<? super T> :  下界通配符 只能写入数据 取数据只能赋值给Object

如果你既想要获取数据,又要写入数据,那么你不能使用通配符类型变量,你可以尝试使用固定的类型变量T,如果还不能解决你的问题,

那么不建议你使用泛型解决你的这个问题。

posted @ 2018-01-06 16:13  get("新技能")  阅读(2284)  评论(0编辑  收藏  举报