与 Java 同样,Kotlin 也提供泛型,为类型安全提供保证,消除类型强转的烦恼。java
class DemoClass<T>(date: T) {//date是任意类型的,避免强转 var todayDate=date }
//指定泛型date为String,三种建立方法 val demo1: DemoClass<String> = DemoClass<String>("2018-01-27") val demo2: DemoClass<String> = DemoClass("2018-01-27") val demo3 = DemoClass("2018-01-27")
//指定泛型date为Int,三种建立方法 val demo1: DemoClass<Int> = DemoClass<Int>(20180127) val demo2: DemoClass<Int> = DemoClass(20180127) val demo3 = DemoClass(20180127)
fun <T> showMsg(msg: T) { }
val msg = showMsg("泛型的使用") val msg1 = showMsg(200) val msg2 = showMsg<String>("指定返回类型")
fun <T> showPrint(printMsg: T) { when (printMsg) { is Int -> println("printMsg是Int类型:$printMsg") is String -> println("printMsg是String类型:$printMsg") else -> println("printMsg类型不是Int也不是String:$printMsg") } } fun main() { showMsg(100) showMsg("2017-01-27") showMsg(true) }
fun <T : Comparable<T>> sort(list: List<T>) {//上界约束 } fun main() { sort(listOf(1, 2, 3))//正确 sort(listOf("1", "2", "3"))//正确 sort(listOf(HashMap<Int,String>))//错误, HashMap<Int, String> 不是 Comparable<HashMap<Int, String>> 的子类型 }
//多个约束,T有多个上限 , where T:类型,T:类型 fun <T> getBetterBig(list: Array<T>, threhold: T): List<T> where T : Number, T : Comparable<T> { return list.filter { it >= threhold }.sorted() }
//建立两个类,继承关系 open class Person(name: String) open class Student(name: String) : Person("PersonA") class Teacher(name: String) : Student("StudentA") fun main() { var person = Person("PersonA") var personList: ArrayList<Person> = arrayListOf(person) var student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) var teacher = Teacher("TeacherA") var teacherList: ArrayList<Teacher> = arrayListOf(teacher) for (name in personList.withIndex()) { println("name is $name")//输出:name is PersonA } for (name in studentList.withIndex()) { println("name is $name")//输出:name is StudentA } for (name in teacherList.withIndex()) { println("name is $name")//输出:name is TeacherA } person = student//正确,由于 Student 是 Person 的子类 /* 编译报错,类型不匹配:Required ArrayList<Person> Found ArrayList<Student> 这是由于,虽然 Student 是 Person 的子类,可是 ArrayList<Student> 并非 ArrayList<Person> 的子类 */ personList = studentList//错误 }
fun main() { var person = Person("PersonA") var personList: ArrayList<out Person> = arrayListOf(person)//使用 out 修饰符,限定类型上限 var student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) personList = studentList//编译正确,这是由于 ArrayList<out Person> 限定了子类的上限为 Person for (name in personList.withIndex()) { println("name is $name")//输出:name is StudentA } }
fun main() { var person = Person("PersonA") var personList: ArrayList<Person> = arrayListOf(person) var student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) var teacher = Teacher("TeacherA") var teacherList: ArrayList<Teacher> = arrayListOf(teacher) /* 如下两种均报类型不匹配错误, */ teacherList = personList//Required ArrayList<Teacher> Found ArrayList<Person> teacherList = studentList//Required ArrayList<Teacher> Found ArrayList<Student> }
fun main3() { val person = Person("PersonA") val personList: ArrayList<Person> = arrayListOf(person) val student = Student("StudentA") val studentList: ArrayList<Student> = arrayListOf(student) val teacher = Teacher("TeacherA") var teacherList: ArrayList<in Teacher> = arrayListOf(teacher)// <in Teacher> 就是容许 Teacher 的超类类型下限为 Teacher for (name in teacherList.withIndex()) { println("name is $name")//输出:name is TeacherA } teacherList = personList for (name in teacherList.withIndex()) { println("name is $name")//输出:name is PersonA } teacherList = studentList for (name in teacherList.withIndex()) { println("name is $name")//输出:name is StudentA } }
再来理解消费者 in 只能用做输入和 生产者 out 只能用做输出的概念:git
不使用 in 和 out 修饰时github
open class Person(name: String) { var myName = "Siberiadante" } class Student(name: String) : Person("PersonA") fun main() { val person = Person("PersonA") var personList: ArrayList<Person> = arrayListOf(person) val student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) personList.add(student)//set 设置值,编译经过 personList[0].myName// get 取值,编译经过 }
做为 < out T>的类型,因为全部类型均为T的下限,没法得知其肯定的类型,因此不能使用 set 方法,只能 get安全
fun main() { val person = Person("PersonA") var personList: ArrayList<out Person> = arrayListOf(person) val student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) /* prohibits(禁止) use of public open fun add(element:E) ! */ personList.add(student)// set 设置值,编译不经过 personList[0].myName// get 取值,编译经过 }
做为 < in T>的类型函数
fun main() { val person = Person("PersonA") var personList: ArrayList<in Person> = arrayListOf(person) val student = Student("StudentA") var studentList: ArrayList<Student> = arrayListOf(student) personList.add(student)//set 设置值,编译经过 /* Unresolved reference : name, */ personList[0].myName// get 取值,编译不经过 }
var list:ArrayList<*> = arrayListOf(100)
fun main() { val person = Person("PersonA") val student = Student("StudentA") val studentList: ArrayList<Student> = arrayListOf(student) /* 至关于 var personList: ArrayList<out Person> = studentList */ var personList: ArrayList<*> = studentList }
fun main9() { val person = Person("PersonA") val personList: ArrayList< Person> =arrayListOf(person) val student = Student("StudentA") /* 至关于 val studentList:ArrayList<in Student> =personList */ val studentList:ArrayList<*> =personList }