文章目录
- [1. 基本概念](#1. 基本概念)
- [2. 理解泛型擦除](#2. 理解泛型擦除)
- [3. 不变,协变,逆变](#3. 不变,协变,逆变)
-
- [3.1 不变](#3.1 不变)
- [3.2 协变](#3.2 协变)
-
- [1. 基础定义](#1. 基础定义)
- [2. 案例分析:接口类List](#2. 案例分析:接口类List)
- [3.3 逆变](#3.3 逆变)
- [4. 星投影](#4. 星投影)
- [5. 内联实化](#5. 内联实化)
1. 基本概念
2. 理解泛型擦除
3. 不变,协变,逆变
3.1 不变
3.2 协变
1. 基础定义
- 如果 A 是 B 的子类型,并且Generic< A> 也是 Generic< B > 的子类型,那么 Generic
可以称之为一个协变类。 - 需要在泛型参数前面加上 out 关键字
- 无法添加元素,只能读取内容(没有add方法)
- UnsafeVariance 在协变(Covariance)中的应用主要是用于打破 Kotlin编译器对泛型类型参数使用位置的限制,从而允许将协变类型参数(out T)用在一些原本不允许的位置(如函数参数、可变属性等),前提是开发者自己能保证类型安全。
2. 案例分析:接口类List
前提是List类使用了out关键字定义泛型参数类型;
String是Any的子类,因此List< String >是List< Any >的子类
kotlin
val stringList : List<String> = ArrayList<String>()
val anyList : List<Any> = stringList
//假设有add方法
anyList.add(1)
val str: String = anyList.get(0) //出错
- List源码
- 使用了out关键字声明
- 没有add方法
- UnsafeVariance的使用,如何理解大白话讲,比如contains中E被当作输入参数(所谓的逆变点),因此就需要加上该注解
kotlin
public interface List<out E> : Collection<E> {
// Query Operations
override val size: Int
override fun isEmpty(): Boolean
override fun contains(element: @UnsafeVariance E): Boolean
override fun iterator(): Iterator<E>
// Bulk Operations
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
// Positional Access Operations
/**
* Returns the element at the specified index in the list.
*/
public operator fun get(index: Int): E
// Search Operations
/**
* Returns the index of the first occurrence of the specified element in the list, or -1 if the specified
* element is not contained in the list.
*/
public fun indexOf(element: @UnsafeVariance E): Int
/**
* Returns the index of the last occurrence of the specified element in the list, or -1 if the specified
* element is not contained in the list.
*/
public fun lastIndexOf(element: @UnsafeVariance E): Int
// List Iterators
/**
* Returns a list iterator over the elements in this list (in proper sequence).
*/
public fun listIterator(): ListIterator<E>
/**
* Returns a list iterator over the elements in this list (in proper sequence), starting at the specified [index].
*/
public fun listIterator(index: Int): ListIterator<E>
// View
/**
* Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive).
* The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.
*
* Structural changes in the base list make the behavior of the view undefined.
*/
public fun subList(fromIndex: Int, toIndex: Int): List<E>
}