您的位置:首页 > 其它

使用泛型实现类型转化-使用通配符上限下限区分协变和逆变采取不同的转化方式

2017-07-26 07:30 651 查看
泛型作用:
 泛型可以用于三种场景:
 1、简单的限定参数类型;
 2、用于类型转化的参数限定,即通配符类型上限和下限,因为在转化的时候,子类转父类是协转,是自动的,父类转子类是逆转,需要编写代码手动处理,即处理方式不同;
 3、结合Java的反射特性由父类获得子类的参数类型或者生成子类的实现,实现代码的集约。
 
 当子类转父类时,是自动的,当父类转子类时则需要单独处理,所以这个时候可以使用泛型进行限定
 这个涉及到一个概念:协变与逆变,也即上面说到的类型转化,斜边是子类转父类,逆变是父类转子类

参数化的类型 List<String>   
实际类型参数 String
泛型         List<E>
形式类型参数 E
无限制通配符类型 List<?>
原生态类型 List
有限制类型参数 <E extends Number>
递归类型限制 <T extends Comparable<T>>
有限制通配符类型 List<? extends Number>
泛型方法 static <E> List<E> asList(E[] a)
类型令牌 String.class


场景:
 ArrayList<Number> b=new  ArrayList<Number>();
 ArrayList<AtomicInteger> c=new  ArrayList<AtomicInteger>();
 入参是 ArrayList<Number>
 可以使用ArrayList<AtomicInteger>处理吗?和泛型结合呢?
 答案:子类可以自动转化为父类-协变,但是父类不能自动转化为子类-逆变

对象 instansof 类,判断 对象是不是这个类的一个实例,子类可以是父类的一个实例,如果是则为true

<? extends Number> 限定参数类型必须为Number或者Number的子类,即Number为类型上限
<? super Number>限定参数类型必须为Number或者Number的超类,即Number为类型下限

实验代码
package com.bestcxx.stu.springmvc.common.test.generic;

import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.Test;

/**
* 泛型作用:
* 泛型可以用于三种场景:
* 1、简单的限定参数类型;
* 2、用于类型转化的参数限定,即通配符类型上限和下限,因为在转化的时候,子类转父类是协转,是自动的,父类转子类是逆转,需要编写代码手动处理,即处理方式不同;
* 3、结合Java的反射特性由父类获得子类的参数类型或者生成子类的实现,实现代码的集约。
*
* 当子类转父类时,是自动的,当父类转子类时则需要单独处理,所以这个时候可以使用泛型进行限定
* 这个涉及到一个概念:协变与逆变,也即上面说到的类型转化,斜边是子类转父类,逆变是父类转子类
* @author Administrator
*
*/
public class GenericList {
/**
* 问题:
* ArrayList<Number> b=new ArrayList<Number>();
* ArrayList<AtomicInteger> c=new ArrayList<AtomicInteger>();
* 入参是 ArrayList<Number>
* 可以使用ArrayList<AtomicInteger>处理吗?和泛型结合呢?
* 答案:子类可以自动转化为父类,但是父类不能自动转化为子类
*/

Integer i;
Number j;
AtomicInteger m;

@Test
public void testAtomicIntegerToNumber(){
ArrayList<Number> b=new ArrayList<Number>();
ArrayList<AtomicInteger> c=new ArrayList<AtomicInteger>();
ArrayList<String> d=new ArrayList<String>();
m=new AtomicInteger(1);
for(int i=0;i<10;i++){
c.add(m);
}
//b=c;//报错
b.addAll(c);//不报错
//b=getListByNumber(d);//报错
b=getListByNumber(c);//不报错

for(Number t:b){
System.out.println(t);
}

}

@Test
public void testNumberToAtomicInteger(){
ArrayList<Number> b=new ArrayList<Number>();
ArrayList<AtomicInteger> c=new ArrayList<AtomicInteger>();
j=1;
for(int i=0;i<10;i++){
b.add(j);
}
//c=b;//报错
//c.addAll(b);//报错
c=getListByAtomicInteger(b);
for(AtomicInteger t:c){
System.out.println(t);
}

}

/**
*· ArrayList<? extends Number> list
* 规定,入参Number为泛型类型的上限,即入参泛型类型可以为Number或者其子类
* 子类可以自动向父类转化,但是父类不能转化为子类
* @param list
* @return
*/
public ArrayList<Number> getListByNumber(ArrayList<? extends Number> list){
ArrayList<Number> li=new ArrayList<Number>();
for(Object o:list){
if(o instanceof Number){
System.out.println("入参类型属于Number的子类");
li.add((Number)o);
}
}
return li;
}

/**
* ArrayList<? super AtomicInteger> list
* 规定泛型类型下限,入参泛型类必须为AtomicInteger或者其之上的超类【public class AtomicInteger extends Number】
* 父类不可以向子类转化
* @param list
* @return
*/
public ArrayList<AtomicInteger> getListByAtomicInteger(ArrayList<? super AtomicInteger> list){
ArrayList<AtomicInteger> li=new ArrayList<AtomicInteger>();
for(Object t:list){
//父类不会是子类的实现,所以下面的代码不会运行,避免强制转化
if(t instanceof AtomicInteger){
li.add((AtomicInteger) t);
}

//li.add((AtomicInteger) t);//强制父类转化为子类,运行时报错

li.add(new AtomicInteger((Integer) t));//单独处理,可以运行
}
return li;
}

}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  泛型 类型转化
相关文章推荐