学习 kotlin 泛型的时候,经常会遇到 in out 这两个词,一会用in 一会用out,为啥这里要用 out ?为啥哪里用 in ?啥什么用 out 啥时候用in ?对应上面问题以前我是晕乎乎的,不是很明白,于是打算写这篇文章梳理一下,搞清楚怎么回事。
Java 泛型
在学kotlin 泛型之前,先回顾一下Java中的泛型 为了方便说明引入下面几个类
具体代码
publicclassAnimal{}publicclassDogextendsAnimal{}publicclassCatextendsAnimal{}publicclassCorgiextendsDog{}publicclassResult{private T data;publicResult(){}publicResult(T data){this.data = data;}publicvoidsetData(T data){this.data = data;}public T getData(){return data;}}
1.不可型变
Result dogResult =newResult();
Result animalResult = dogResult;
虽然 Dog 是 Animal 的子类,但是Java 泛型是不可以型变的,Result
对象不能赋值给 Result
, 他们之间没有关系。 如果 Java 泛型不是这样设计的就容易造成运行时异常,例如
Result dogResult =newResult();
Result animalResult = dogResult;
animalResult.setData(newAnimal());
Dog dog = dogResult.getData();
所以 Java 这样设计是为了安全考虑。 为了安全,这样的限制显然会失去一些API的灵活性。于是 Java 提供有限制通配符 ? extends X
、? super X
、 来提升API 的灵活性。
2.型变性通配符 —— ? extends
Result dogResult =newResult(newDog());
Result animalResult = dogResult;
Animal animal = animalResult.getData();