private void testUp(List 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 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 // 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 // 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&lt;? extends SomeThing&gt; 它的意义可以理解为:一个具有任何从SomeThing继承的类型的列表。    超类型 通配符 超类型 通配符 在语法中写为: List&lt;?... 导入包错误,去掉上面俩个包,导入下面俩个包 //import org.junit.platform.commons.logging.Logger; //import org.junit.p