/**
* 通配符上下限测试
*/
@ComponentScan("com.*.*")
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("dev")
@Slf4j
public class LimitTest {
/**
* 说明:
* OptionVO与BrandVO继承BaseVO
* AreaCodeVO不继承BaseVO
*
*/
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<OptionVO> exOptionUpList = new ArrayList<>();
OptionVO optionVO = new OptionVO();
optionVO.setId(1L);
optionVO.setOptionName("品类1");
optionVO.setAttributeCode("A01");
exOptionUpList.add(optionVO);
testUp(exOptionUpList);
List<BrandVO> exBrandUpList = new ArrayList<>();
BrandVO brandVO = new BrandVO();
brandVO.setId(1L);
brandVO.setBrandName("品牌1");
exBrandUpList.add(brandVO);
testUp(exBrandUpList);
List<AreaCodeVO> exAreaUpList = new ArrayList<>();
AreaCodeVO areaCodeVO = new AreaCodeVO();
areaCodeVO.setArea("1");
exAreaUpList.add(areaCodeVO);
// Required type:List<? extends BaseVO>
// Provided:List<AreaCodeVO>
testUp(exAreaUpList);//因为AreaCodeVO不是BaseVO或者它的子类!!!所以《标红》 原因看上面
}
@Test
public void doTestDown() {
List<OptionVO> 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<OptionVO>
testDown(exOptionDownList); //因为OptionVO不是BaseVO或者它的父类!!!所以《标红》
List<BrandVO> exBrandDownList = new ArrayList<>();
BrandVO brandVO = new BrandVO();
brandVO.setId(1L);
brandVO.setBrandName("品牌1");
exBrandDownList.add(brandVO);
testDown(exBrandDownList);//因为BrandVO不是BaseVO或者它的父类!!!所以《标红》
List<BaseVO> exBaseDownList = new ArrayList<>();
BaseVO baseVO = new BaseVO();
baseVO.setCreator("3");
exBaseDownList.add(baseVO);
testDown(exBaseDownList);
List<BaseVO> 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来写入