通配符
Java 中用?表示通配符,由于参数值是未知类型的容器类,所以只能读取其中元素,不能向其中添加元素, 因为,其类型是未知,所以编译器无法识别添加元素的类型和容器的类型是否兼容,唯一的例外是NULL
public static void main(String[] args) {
List<?> data = new ArrayList<>();
data.get(0); //正确,可以读取
data.add("1"); //错误,无法添加
data.add(null);
}
Kotlin中用* 表示通配符,又称星号投射,表示你并不知道类型参数的任何信息, 但是仍然希望能够安全地使用它. 这里所谓"安全地使用"是指, 对泛型类型定义一个类型投射, 要求这个泛型类型的所有的实体实例, 都是这个投射的子类型。其实就是*代指了所有类型,相当于Any?。
fun main() {
val data: ArrayList<*> = arrayListOf("String", 1, 1.2f)
data.add("111") //报错
val item = data[0] //正确
}
有界类型参数
首先定义两个类,为继承关系
public class FuClass {
}
public class ZiClass extends FuClass {
}
声明java的上限:
//单个上限
public class JavaGeneric<T extends FuClass> {
}
//多个上限
public class JavaGeneric<T extends FuClass & Serializable> {
}
声明kotlin的上限:
//单个上限
class KotlinGeneric<T : FuClass>{
}
//多个上限
class KotlinGeneric<T> where T: FuClass, T: Serializable{
}
权限取读模式
Java可读不可写模式:
FuClass fuClass = new FuClass();
ZiClass ziClass = new ZiClass();
void test(){
List<? extends FuClass> list = new ArrayList<ZiClass>();
list.add(fuClass);//报错
list.add(ziClass);//报错
list.add(null);//可以添加null
FuClass fuClass = list.get(0);//可以获取
}
Java可写不可读模式:
void test(){
List<? super ZiClass> list = new ArrayList<FuClass>();
//可以添加
list.add(ziClass);
//不能获取
ZiClass ziClass1 = list.get(0);
}
Kotlin可读不可写模式:
val fuClass = FuClass()
val ziClass = ZiClass()
fun test(){
val list: MutableList<out FuClass> = ArrayList<ZiClass>()
list.add(fuClass)//报错
list.add(ziClass)//报错
val item = list[0]//可以获取
}
Kotlin可写不可读模式:
fun test(){
val list: MutableList<in ZiClass> = ArrayList<FuClass>()
//能添加
list.add(ziClass)
//不能获取
val item = list.get(0)
}
Kotlin独有的东西:
这种模式kotlin独有,Java不允许在申明泛型的时候控制读写模式
//这个类,就是只能获取,不能修改
//声明的时候加入一劳永逸
class Test<out T>(private val t: T) {
fun get(): T {
return t
}
}
//这个类只能修改,不能获取
class Test<in T>(private var t: T) {
fun set(data: T) {
t = data
}
}