使用泛型实现类型转化-使用通配符上限下限区分协变和逆变采取不同的转化方式
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;
}
}
泛型可以用于三种场景:
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;
}
}
相关文章推荐
- Java基础(21):泛型—泛型的定义、用法与类型通配符的使用方式
- [疯狂Java]泛型:类型参数多态问题、类型通配符(?)、类型通配符的上下限、类型参数的上限(类、接口)
- 牛客网Java刷题知识点之泛型概念的提出、什么是泛型、泛型在集合中的应用、泛型类、泛型方法、泛型接口、泛型限定上限、泛型限定下限、 什么时候使用上限?泛型限定通配符的体现
- c#打包文件解压缩 C#中使用委托、接口、匿名方法、泛型委托实现加减乘除算法 一个简单例子理解C#的协变和逆变 对于过长字符串的大小比对
- 泛型通配符的使用及类型限定上限
- 深入理解泛型,类型通配符<?>,类型通配符上限,下限
- 在 Java 的泛型类型中使用通配符
- 在 Java 的泛型类型中使用通配符
- (转)stringstream类的使用(实现string类型与其余类型的转化)
- 泛型类型通配符?的使用
- 泛型实现不同类型的数据生成XML文件
- 泛型通配符:泛型上限通配符? extends 上限类型
- Java基础:泛型类型的子类及通配符的使用
- 一个使用泛型堆栈模块创建的两个容纳不同类型数据的实例
- [译]委托和接口泛型参数类型的协变和逆变
- 泛型类型的子类及通配符的使用
- DLL函数定义和函数实现写函数类型的不同, 引起不能使用Dll中的函数
- REST API下的ArcServer 9.3.0与9.3.1使用Javascript实现路径分析的不同方式
- 在 Java 的泛型类型中使用通配符
- 使用UI Automation实现自动化测试--5 (Winfrom和WPF中弹出和关闭对话框的不同处理方式)