private void testUp(List extends BaseVO> exUpList){
OptionVO optionVO = new OptionVO();
optionVO.setAttributeCode("A02");
// Required type:capture of ? extends BaseVO
// Provided:OptionVO
exUpList.add(optionVO); //无法添加optionVO !!!《标红》 原因看上面
BaseVO baseVO = new BaseVO();
baseVO.setCreator("1");
exUpList.add(baseVO);//无法添加baseVO !!!《标红》
exUpList.forEach(exUp->{
String creator = exUp.getCreator();
String updater = exUp.getUpdater();
exUp.setCreator("6");
exUp.setCreator("7");
private void testDown(List super BaseVO> exDownList){
OptionVO optionVO = new OptionVO();
optionVO.setAttributeCode("A02");
exDownList.add(optionVO);
BaseVO baseVO1 = new BaseVO();
baseVO1.setCreator("2");
exDownList.add(baseVO1);
AreaCodeVO areaCodeVO = new AreaCodeVO();
areaCodeVO.setArea("4");
//Required type:capture of ? super BaseVO
// Provided:AreaCodeVO
exDownList.add(areaCodeVO);//没有继承关系!!!《标红》
exDownList.forEach(exDown->{
// Cannot resolve method 'getCreator' in 'Object'
String creator = exDown.getCreator();//无法获取creator !!!《标红》 原因看上面
String updater = exDown.getUpdater();//无法获取updater !!!《标红》
// Cannot resolve method 'setCreator' in 'Object'
exDown.setCreator("8");//无法设置creator !!!《标红》
exDown.setUpdater("9");//无法设置updater !!!《标红》
@Test
public void doTestUp() {
List
exOptionUpList = new ArrayList<>();
OptionVO optionVO = new OptionVO();
optionVO.setId(1L);
optionVO.setOptionName("品类1");
optionVO.setAttributeCode("A01");
exOptionUpList.add(optionVO);
testUp(exOptionUpList);
List exBrandUpList = new ArrayList<>();
BrandVO brandVO = new BrandVO();
brandVO.setId(1L);
brandVO.setBrandName("品牌1");
exBrandUpList.add(brandVO);
testUp(exBrandUpList);
List exAreaUpList = new ArrayList<>();
AreaCodeVO areaCodeVO = new AreaCodeVO();
areaCodeVO.setArea("1");
exAreaUpList.add(areaCodeVO);
// Required type:List extends BaseVO>
// Provided:List
testUp(exAreaUpList);//因为AreaCodeVO不是BaseVO或者它的子类!!!所以《标红》 原因看上面
@Test
public void doTestDown() {
List exOptionDownList = new ArrayList<>();
OptionVO optionVO = new OptionVO();
optionVO.setId(1L);
optionVO.setOptionName("品类1");
optionVO.setAttributeCode("A01");
exOptionDownList.add(optionVO);
// Required type:List super BaseVO>
// Provided:List
testDown(exOptionDownList); //因为OptionVO不是BaseVO或者它的父类!!!所以《标红》
List exBrandDownList = new ArrayList<>();
BrandVO brandVO = new BrandVO();
brandVO.setId(1L);
brandVO.setBrandName("品牌1");
exBrandDownList.add(brandVO);
testDown(exBrandDownList);//因为BrandVO不是BaseVO或者它的父类!!!所以《标红》
List exBaseDownList = new ArrayList<>();
BaseVO baseVO = new BaseVO();
baseVO.setCreator("3");
exBaseDownList.add(baseVO);
testDown(exBaseDownList);
List exBrandUpList = new ArrayList<>();
BrandVO brandVO1 = new BrandVO();
brandVO1.setId(3L);
brandVO1.setBrandName("品牌3");
exBrandUpList.add(brandVO1);
OptionVO optionVO1 = new OptionVO();
optionVO1.setId(4L);
optionVO1.setOptionName("品类4");
optionVO1.setAttributeCode("A04");
exBrandUpList.add(optionVO1);
AreaCodeVO areaCodeVO = new AreaCodeVO();
areaCodeVO.setArea("1");
// Required type:BaseVO
// Provided:AreaCodeVO
exBrandUpList.add(areaCodeVO);//因为areaCodeVO父类不是BaseVO!!!所以《标红》
testDown(exBrandUpList);
由此可见:
<? extends 上界>上边界通配符,只能读数据,不能写数据。
<? super 下界>下边界通配符,只能写数据,不能读数据。
? extends T语法,比如 ? extends Number
由于无法确定子类型,可能是Integer,那么写入一个Double合适吗?不合适;可能是Double,那么写入一个Integer合适吗?不合适。因此就索性禁止写入了,但是由于知道上界,可以按照 T类型来读。
? super T语法,由于无法确定父类型,因此法无法读定义 A a = array.get(0), (即期望能自动转换的,而不是手动进行类型转换的),但是由于知道下界,可以按照 T来写入
引用文章:
https://blog.csdn.net/m0_45406092/article/details/125344529?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165899777616782395356769%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=165899777616782395356769&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~pc_rank_34-2-125344529-null-null.142^v35^pc_rank_34&utm_term=java%20%E9%80%9A%E9%85%8D%E7%AC%A6%20%E6%BA%90%E7%A0%81&spm=1018.2226.3001.4187
环境:Windows XP Professional、JDK 1.6、Ant 1.7<br>说明:
Java
泛型的动机是为解决类型转换在编译时不报错的问题。另外由于“范型编程”(Generic Programming)的推广,于是2004年JDK 5.0引用范型标准。本例子说明演示了
Java
范型使用的动机、范型类的使用、范型方法的使用,以及范型的缺陷:类型擦除(
type
erasure).因为,现在
Java
的反射机制不能确定集合中的对象类型!<br>在实际应用中,如果能够灵活应用范型和反射,那么该
Java
程序员可以设计出非常好的东西来,从而解决实际开发简化开发过程的目的。比如,在EJB 2.0开发客户端应用时,如果使用范型和反射,可以把EJB 2.0的标准使用动作--“从远程home接口得到远程接口过程”--可以简化为:使用者可以直接得到远程接口,从而呼叫远程接口定义的业务逻辑方法。这个动作正是EJB 3.0实现的动作!!<br>注意:本示例不建议
Java
初学者阅读。<br>
当深入了解泛型后,就会发现很多东西初看起来是没有意义的。例如,尽管可以申明ArrayList.class,但是不能申明为Array.class。例如:
class Manipulator {
private T obj;
public Manipulator(T x) { obj = x; }
// Error: cannot find symbol: method
?
通配符
类型- <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类;
<? super T> 表示类型下界(
Java
Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object;extends比如,我们现在定义:List<? extends T>首先你很容易误解它为继承于T的所有类的集合,你可能认为,你定义的这个List可以用来put任何
在上面的示例中,我们加载了一个名为file.txt的文件,并将其转换为InputStreamResource类型,然后将其作为响应体返回给客户端。在Spring Boot中,可以使用Spring框架提供的AOP(面向切面编程)机制来实现切面编程,通过AOP可以在不修改原有代码的情况下,对系统进行横向扩展,例如添加日志、性能监控、事务管理等功能。在上面的示例中,我们通过SendGrid提供的
Java
SDK来发送邮件,先创建一个Mail对象,并设置相关的邮件参数,然后使用SendGrid的API来发送邮件。
不知道读者们平时使用泛型多不多,自认为对泛型了解多少呢?本文笔者带你重学一下泛型,不只从语法的角度,尽可能从本质的角度上去理解它,并用实例代码去解释,主要内容如下:
泛型的声明和实例化
extends 和 super 的使用
泛型的协变和逆变
泛型的类型擦除
泛型方法和类型推断
泛型的嵌套和重复
Kotlin泛型
如果你对以上有不是很清楚的知识点,建议看完以下内容,相信你会有所收获!
简述 上篇我说到了类型擦除的缺点,也提供了一些解决方法。本篇我将说一下解决方法中的细节部分,也就是
通配符
。
通配符
子类型
通配符
子类
通配符
在语法中写为: List<? extends SomeThing> 它的意义可以理解为:一个具有任何从SomeThing继承的类型的列表。 超类型
通配符
超类型
通配符
在语法中写为: List<?...
导入包错误,去掉上面俩个包,导入下面俩个包
//import org.junit.platform.commons.logging.Logger;
//import org.junit.p