问题
需要对中间件、应用2个类型的数据进行domain的数据进行解析,2应用都继承自CmdbBaseApp,此时parseDomain的时候接受参数 List<cmdbBaseApp>
类型,同时处理2种类型数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class CmdbBaseApp { private int id; private String domain; }
public class CmdbMiddleResponse extends CmdbBaseApp { }
public class CmdbProjectResponse extends CmdbBaseApp { }
private void parseDomain(List<CmdbBaseApp> apps) { }
|
现象
编译报错
1 2 3 4 5
| parseDomain(new ArrayList<CmdbMiddleResponse>());
java: 不兼容的类型: java.util.ArrayList<com.dada.alarm.model.CmdbMiddleResponse>无法转换为java.util.List<com.dada.alarm.model.CmdbBaseApp>
|
解析
由于数组是协变的,泛型是不变的,所以 List<CmdbMiddleResponse>
不等于 List<CmdbBaseApp>
。
数组是协变的,泛型是不变的。泛型可以通过通配符实现协变和逆变(pecs)。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 解法一: 利用数组协变
List<CmdbBaseApp> apps = new ArrayList<>(); apps.addAll(new ArrayList<CmdbMiddleResponse>()); apps.addAll(new ArrayList<CmdbProjectResponse>()); parseDomain(apps);
解法二: 泛型实现协变 private void parseDomain(List<? extends CmdbBaseApp> apps) { }
parseDomain(new ArrayList<CmdbMiddleResponse>());
|
参考:
https://rumenz.com/java-topic/java/generics/java-generics-what-is-pecs-producer-extends-consumer-super/index.html
https://juejin.cn/post/6911302681583681544