Kotlin基础
大约 19 分钟
Kotlin基础
intellid IDE查看函数注释
按一下 shift + q 显示提示框
连按两下 shift +q 显示新的窗口
使用Itellij IDE显示kotlin字节码,连续按两次shift
包名
package cn.rxdidi
// 导入包
import cd.rxdidi
常量
const val a = "123":
fun mian()
{
println("编译时常量只能在函数外申明")
}
变量
var a; // 可以重复赋值
val b; // 只能赋值一次,相当于常量
var a :int = 1; // int类型的变量
// 多行文本,.trimIndent()除去空格字符
var str = """
adf
asdf
asdf
asdf
asdf
""".trimIndent()
println(str)
// val str = "字符串模板";
println("类似C#的语法,$str")
数组
fun Aarr(){
// 创建一个一维数组
var arr = Array(5){i->i*5}
// 循环输出数组,it = item
arr.forEach { println(it) }
// 创建一维数组数组
var arr2 = arrayOf(1,2,3,4,5)
arr2.forEach { println(it) }
// 一维数组
arrayOf("1","2","3")
println("一维数组,字符串")
var ArrStr = Array(5){""}
ArrStr[0] = "0";
ArrStr[1] = "1";
ArrStr[2] = "2";
ArrStr[3] = "3";
ArrStr[4] = "4";
for (i in ArrStr) println(i)
// 创建数组
var arr3 = IntArray(5){6}
arr3[1] = 34;
println("arr3-1 = "+arr3[1])
arr3.forEach { println(it) }
// 访问数组
val arr3_3 = arr3.get(1)
println("使用get访问数组: " + arr3_3)
// 设置数组
arr3.set(2,53)
val arr3_2 = arr3.get(2)
println("使用set访问数组: " +arr3_2)
val str = "字符串模板";
println("类似C#的语法,$str")
// 多维数组
println("多维数组")
val arrList = Array<Array<String>>(2){Array<String>(2){""} }
val arrList2 = Array(2){Array(2){""} }
arrList2[0][0] = "一";
arrList2[0][1] = "二";
arrList2[1][0] = "一一";
arrList2[1][1] = "一二";
for ((value,item) in arrList2.withIndex())
{
for (j in item.indices){
println(arrList2[value][j])
}
}
// 多维数组
val arrArr = Array(2){Array<String>(2,{""}) }
arrArr[0][0] = "10";
arrArr[0][1] = "20";
arrArr[1][0] = "30";
arrArr[1][1] = "40";
var i = 0;
var j = 0;
for (item in arrArr){
for ( itms in item[i]){
println(arrArr[i][j])
j++;
}
i++;
j=0;
}
// 3维数组
var arrArrArr = Array<Array<Array<String>>>(3){Array<Array<String>>(3){Array<String>(3){""} }}
// 3维数组
var arrArr2 = Array(3){Array(3){Array<String>(3,{""})} }
}
ForWhenWhlieIf
fun ForWhenWhileIf(){
// 等同于 0 <= i && i <= 3
for (item in 0..3) println(item)
// for循环数组, 相当于C#的foreach
var arr = arrayOf(1,2,3,4,5,6);
for (item in arr) println(item)
// 区间表达downTo , 相当于: 10 = 3 结束本次递送;
println("区间表达downTo")
for (item in 10 downTo 3) println(item)
// 区间表达 step, 每循环一次跳过4次,如果step = 1说明不跳过循环, = 0 则崩溃
println("区间表达 step, 每循环一次跳过4次")
for (item in 1..10 step 4) println(item)
// 这条语句=
println("区间表达式,反向递送 downTo 说明: i = 6 , i == 3 break")
println("反向循环,循环6次,第三次结束,每循环一次跳过2此")
for (i in 6 downTo 3 step 2) {
println(i)
}
// for 使用(item,value) 等同于c#的foreach
println("for 使用(item,value) 等同于c#的foreach")
var arr2 = arrayOf(50,40,30,20,10)
for((value,item) in arr2.withIndex())
{
println(value)
println(item)
}
// for使用循环,item值为循环次数
println("for使用循环,item值为循环次数")
for (item in arr2.indices)
{
println(arr2[item])
}
// if语句用法
println("if语句作为表达式")
val a = 1;
val b = 2;
var ifLarge = if(a>b)b else a;
println(ifLarge)
// 正常的if语句
var max:Int;
if(a > b)
{
max = a;
}else{
max = b;
}
// when语句, 等同于其他语言的switch,但是when的用处更多
println("when语句")
var whenVal = "ok"
when(whenVal){
"ok" -> println("whenVal = ok")
"no" -> println("whenVal = no")
else -> println("whenVal = null") // else为默认值
}
// when, 相当于其他语言的
/*
* case 1:
* case 2;
*
* break;
* */
var whenVal2 = 0;
when(whenVal2){
1,2 -> println("whenVal2 = 1 or 2")
else ->{
println("whenVal2 = null")
}
}
// when 检测一个值 is 或 !is 一个特定的值
// 下面这个表示:如果字符串以prefix开头返回true否则false
fun hasprefix(x:Any) = when(x){
is String -> x.startsWith("prefix") // 如果字符串包含prefix开头则返回true
is Int -> true // 如果是int类型返回true
else -> false
}
var istrue = hasprefix("prefix is true")
println(istrue)
var istrue2 = hasprefix(2)
println(istrue)
}
range表达式,表示 几到几之间, 0 .. 10 or 1..3 = 0到10之间 或 1到3之间
val a = 3;
if(a in 0 .. 3)
{
println("他在0到3之间")
}
if(a !in 0..3)
{
println("他不在0到3之间")
}
// downTo
for(item in 10 down 1) println(" 反向递送 = 10 9 8 7 .. 1 ");
// step
for (item in 10 step 2) println("每循环一次跳过两次");
// until
for(item in 1 until 10) prinln("i in [1, 10), 10被排除")
when表达式,满足某个条件后执行相应代码
val a = "ok";
when(a)
{
"ok" -> println("a = ok")
else -> println("a 等于啥我也不知道啊")
}
StringTemplate 字符串模板
val a = "我是变量a";
val b = "我是变量b";
var S = "字符串模板可以使用变量和表达式: 变量a =$a 变量b = $b ";
println(S)
println("同时StringTemplate还可以使用表达式")
val isTrue = false;
val S2 = "判断一个值是否为true : ${if(isTrue) " = true" else " = false"}";
println(S2)
函数
// age 默认值 = 18
// FunctionParpam返回值为空,Unit = C#语言的void
private fun FunctionParpam(age :Int = 18, name :String):Unit{
}
TODO抛出异常,终止代码运行
private fun FunctionParpam(age :Int = 18, name :String):Unit{
// 使用ToDo函数可以抛出异常,终止代码运行
// ToDo("错误原因")
}
反引号申明 特殊字符方法
· 这个符号在tab键上面
fun `我是反引号方法`(){
println("反引号申明特殊字符方法")
println("反引号申明特殊字符方法")
}
匿名函数
fun `匿名函数`(){
// 匿名函数使用方法就是C#的lambad
var Anonymous = "用匿名函数判断此字符串重复的字符串数量".count({string -> string == '字'})
println(Anonymous)
}
匿名函数隐式返回
fun `匿名函数隐式返回`(){
// 匿名函数声明方法一
val BlessingFunction1:()-> String = {
"隐式返回默认返回最后一行,无需return"
}
// 匿名函数隐式返回2
val BlessingFunction2:() -> String
BlessingFunction2 = {
"隐式返回默认返回最后一行,无需return"
}
}
匿名函数只有一个参数时,可以用it代替
fun `匿名函数只有一个参数时`(){
var AnonymousIt:(Str:String)->String = {
it->
"匿名函数只有一个参数时,可以用it代替:{$it}"
}
println(AnonymousIt("我是匿名函数的参数,当匿名函数只有一个参数时可以用it代替"))
}
匿名函数类型推断,大大减少代码量
var BlessingFunction = {
"当匿名函数没有参数时,简略写法可以这么写"
}
var blessingFunction2 = {
Str:String,int:Int->
"当匿名函数有参数时,简略写法:参数一 = $Str, 参数二 = $int"
}
匿名函数就是Lambda#
kotlin的Lambda
()-> String {
Param:String ->
"我是kotlin的lambda函数,参数一调用:$Param"
}
C#的Lambda
Func<参数 Param, string 返回值>= a => $"Lambda参数一的值为: {a}";
当函数参数是lambda时
fun `当Lambda被当作参数时`(){
var Lambda:(String) -> String = {
it ->
it // 返回it , it = 默认参数
}
// 调用函数,函数内含有Lambda
// 使用此方法调用,感觉非常麻烦
println("使用常规方法调用函数")
val a = FunLambda(18,Lambda)
// 调用函数,函数内含有Lambda
// 括号里面写函数的参数,大括号里面就是Lambda
println("使用简略方法调用函数")
val b= FunLambda(18){
it // 返回it , it = 默认参数
}
}
fun FunLambda(age : Int, Name:(String)->String){
println("年龄 = $age , 姓名 = ${Name("匿名函数当参数")}")
}
内联函数 inline
// 自己认为:
// 内联函数:重复、多次使用同一个函数可以使用内联函数来减少损耗
inline fun InlineFun()
{
println("当一个函数被多次调用时,可以使用inline来减少服务器压力")
}
函数处理可以用lambda作为参数之外还可以使用函数做为参数,使用 :: + 函数名即可
fun `函数除了可以调用Lambda以外还可以直接调用函数`(){
// 函数除了可以用lambda作参数之外,还可以用函数做参数,使用 :: + 函数名
FunLambda(18,::Name)
}
fun Name(Str:String):String{
return Str;
}
fun FunLambda(age : Int, Name:(String)->String){
println("年龄 = $age , 姓名 = ${Name("匿名函数当参数")}")
}
当返回类型为Lambda时
// 声明
fun `返回类型是Lambda时`():(String)->String {
return {
"返回类型为 Lambda时,参数一的值为: $it"
}
}
// 调用
val WriteLambda = 返回类型是Lambda时()
println(WriteLambda("我是参数一的值"))
可空类型,var str:String? = "";
var str:String? = "可空类型";
安全调用操作符
var str:String? = "可空类型";
str = null;
//可空类型必须使用?,否则会报错
str?.trim();
可空类型使用let函数
// 可空字符串使用 let函数
fun nullLet(){
var str:String? = "本字符串可以为空"
str = null
// 使用let函数
str = str?.let{
it:String->
if(it.length > 5){
"大于5"
}else{
"小于5"
}
}
println(str)
}
非空运算符,!!.
// 非空运算符,如果为空发出异常
fun noNull(){
var str:String? = "非空运算符,如果为空发出异常";
println(str!!.length);
}
合并操作符,相当于C#的三元表达式 ? :
// 空合并操作符 ?:
fun `空合并操作符`(){
var str:String? = "空合并操作符";
str = null
// 不为空为左,为空为右
println(str?.let { it.capitalize() } ?: "str is null")
}
自定义异常,继承exception
// 自定义异常
fun `自定义异常`(){
var str:String? = null;
try {
// 触发异常
throw customException();
// 如str不为空则str +1
str!!.plus("+1");
}catch (e:Exception){
println(e)
}
}
// 自定义异常,继承Exception
class customException() : Exception("为空")
检测参数是否为空,如果为空发出自定义异常
// 检测参数不为空,如果为空返回自定义异常
fun `检测参数不为空`(){
var str:String? = null;
checkNotNull(str,{"参数为空"})
}
解构语法,把list赋值给变量
// 解构语法
fun `解构语法`(){
var str = "a,b,c";
var strList = str.split(',')
// 常规调用方式
//println(strList[0])
// 解构语法, 把list赋值给变量
var (str1,str2,str3) = strList
println(str1)
}
replace(字符串替换) + regex(正则表达式)
// replace
fun replaceA(){
var str = "a b c d e f g";
var str2 = str.replace(regex = Regex("[^abg]")){
when(it.value){
"c" -> "1"
"d"->"2"
"e"->"3"
else -> it.value
}
}
println(str)
println(str2)
}
== and ===
// == and ===
fun `==and===`(){
var str1 = "String";
// 将字符串首字母改为大写
var str2 = "string".capitalize();
// = true
println(str1 == str2)
// = false
println(str2 === str1)
}
字符串遍历
"字符串遍历".forEach{
println(it);
}
数字转换
// 数字转换
fun `数字转换`(){
// 如果转换失败则为空
var a :Int? = "9.9".toIntOrNull()
// = 9 ,但四舍五入之后为10
var b = 9.9.roundToInt();
// 格式化字符串
var c = "%.2f".format(3.14125);
println(a)
println(b)
println(c)
}
apply函数,在apply里面调用类的方法时无需使用变量名
let and apply
// let 与 apply对比
// let 传入前者结果为参数且返回结果为最后一行
// apply 不传入参数,执行结果赋值给变量
fun letAndApply(){
// let 使用
var str = listOf(1,2,3).last().let{
it * it
}
println(str)
// let + :? 代替if else
println(formatGreeting(null));
println(formatGreeting("Ddcheat"));
// apply前后对比
File("C:\\kotlin.txt").apply{
setReadable(true)
setWritable(true)
setExecutable(false)
}
var createFile = File("C:\\kotlin2.txt")
createFile.setExecutable(false)
createFile.setReadable(true)
createFile.setWritable(true)
}
// 使用let + :? 代替 if else
fun formatGreeting(name:String?) : String? {
return name?.let {
"welcome $it"
} ?: "what`s your name"
}
run函数
// run 函数 run 和 apply相比 run接收上一个对象,返回结果为最后一行
fun runandApply(){
var file = File("C:\\Users\\29663\\Desktop\\服务器.txt")
// run和apply, apply是配置函数, run 是返回函数
var result = file.run{
readText()
}
println(result)
// run 还可以使用 引用函数
// 可以使用多个run
var resultLength = result.run(::textISlength)
?.run(::textLengthGreaterThan)
println(resultLength)
}
fun textISlength(text:String?) = text?.length
fun textLengthGreaterThan(length:Int): String{
return if(length > 5){
"string Greater Than 5"
}else{
"String less Than 5"
}
}
with and run
// with 跟 run 相似, 但 with 需要传入参数
fun withAndrun(){
var a = "判断字符串长度".run{
length
}
var b = with("判断字符串长度"){
length
}
println(a)
println(b)
}
also
// also 跟 let 函数相似, also 接收对象,返回接受的对象, let 接收对象,返回lambda
fun alsoAndlet(){
var file = File("C:\\Users\\29663\\Desktop\\服务器.txt").also{
println("文件名 = " + it.name)
}.also{
println(it.readText())
}
}
takeif
// takeif
fun takeif(){
var text = File("C:\\Users\\29663\\Desktop\\服务器.txt").takeIf {
it.canRead() && it.exists()
}?.readText()
println(text)
}
takeUnless , 是takeif的辅助函数,takeif为真时返回对象,而takeunless为假时返回对象
// takeUnless 当判定条件为假时返回对像,为真时返回null
fun takeunless(){
// 如果 isHidden为假则执行后面的函数,如果为真则返回null
var text:String? = File("C:\\Users\\29663\\Desktop\\服务器.txt").takeUnless{
it.exists()
}?.let{
"这个文件不存在"
}
println(text)
}
list集合
// list
fun list(){
var strlist :List<String> = listOf("a","b","c")
// 访问指定索引,如果不存在则为自定义值,Unknown
println(strlist.getOrElse(3){"Unknown"})
// 访问指定索引值,如果为空,则 = Unknown
println(strlist.getOrNull(4) ?: "Unknown")
}
mutableLIst
// mutableList 可变集合, list为不可变集合
fun mutablelist(){
var mutablelist = mutableListOf("a","b","c")
// 添加
mutablelist.add(3,"d")
mutablelist.add("e")
// 删除
mutablelist.remove("e")
println(mutablelist)
// mutablelist 为可变集合, listof为不可变集合
// 可变集合 不可变集合可以互转
mutableListOf("a","b","c").toList()
listOf("a","b","c").toMutableList()
}
mutator
// mutator
fun mutator(){
// 需要使用val 使用var会报错
val mutablelist = mutableListOf("a","b","c")
// 添加元素
mutablelist += "d";
// 删除元素
mutablelist -= "a"
// lambda删除元素
mutablelist.removeIf{
it.contains("b")
}
println(mutablelist)
}
遍历列表
// foreach list
fun foreachList(){
val mutablelist = mutableListOf("a","b","c")
// 第一种方式
for (s in mutablelist) {
println(s)
}
// 第二种方式
mutablelist.forEach {
println(it)
}
// 第三种方式
mutablelist.forEachIndexed{
index,item->
println("$index , $item")
}
}
解构语法忽略赋值
fun `解构语法忽略赋值`(){
val list = listOf("a","b","c")
// 使用下划线忽略对b的赋值
val (a,_,b) = list
println(a)
println(b)
}
SetList 不可变Set集合
// setList 和list 的区别在, setList不可以有重复元素而 list可以有重复元素
fun setlist(){
val setlist = setOf("a","b","c")
println(setlist.elementAt(1))
}
MutableSetList 可变Set集合
// 可变的Setlist
fun mutableSetList(){
val mutableSetlist = mutableSetOf("a","b","c")
// 添加或删除元素
mutableSetlist.add("d")
mutableSetlist.removeIf{it.contains("a")}
// 添加或删除元素
mutableSetlist += "e"
mutableSetlist -= "b";
println(mutableSetlist)
}
集合转换, 快捷函数
// 集合转换 和 快捷函数
fun listTOset(){
val list = listOf("a","a","b")
// 去重复元素,但很麻烦
val list1 = list.toSet().toList()
// 去重复元素函数 distinct
val list2 = list.distinct();
println(list)
println(list1)
println(list2)
}
mapList
// mapList key value模式
fun mapList(){
// 第一种创建方式
val maplist1 = mapOf("a" to 10,"b" to 20 ,"c" to 30)
// 第二种创建方式
val maplist2 = mapOf(Pair("a",10),Pair("b",20),Pair("c",30))
// 索引取值
println(maplist1[0])
// 取值
println(maplist2.getValue("a"))
println(maplist2.getOrElse("d"){"unknown"})
// 递送
maplist1.forEach { key, value ->
println("$key, $value")
}
// 递送二
maplist2.forEach {
println("${it.key}, ${it.value}")
}
// 递送三
for (entry in maplist2) {
println("${entry.key}, ${entry.value}")
}
}
field , 类属性自定义get / set时使用
class FirstClass {
var str = "capitalize"
get() = field.capitalize()
set(value) {
field = value.trim()
}
}
面向对象
// 构造函数
class ConstructorClass constructor(name:String , age:Int) {
}
// 构造函数,无需constructor
class ConstructorClassTwo (name:String, age:Int){
}
// 使用Init初始化代码
class InitClass(var name:String){
init {
// 使用also输入此字符串
"name = ${name}".also(::println)
}
}
// 继承类 , 使用open关键字,其变量或方法可以被继承同样使用open
open class parentClass(_name:String, _age:Int){
// 子类不能重写父类的 var ,比如把var 覆盖为 val
open var name = "";
open var age = 0;
init {
name = _name;
age = _age
}
open fun writeLine() :String{
return "年龄 = ${age} , 姓名= ${name}"
}
}
// 子类, 使用override
class sunClass(override var age:Int,override var name:String) : parentClass(_age = age,_name = name){
// 继承后,使用super()初始化父类
//constructor():super();
override fun writeLine():String {
return "override返回 年龄 = ${age} , 姓名= ${name}"
}
// 如果要调用父类的属性或方法可以使用super
fun writeline(){
// 调用父类方法
super.writeLine().also(::println)
// 如果继承多个类或interface 可以这么调用
super<parentClass>.writeLine().also(::println)
// 调用父类属性
println("父类中age = ${super.age}")
}
}
// 抽象类
abstract class AbstractClass:parentClass{
// 给父类属性赋值
constructor(age: Int,name: String):super(name, age);
override fun writeLine(): String {
return super.writeLine()
}
}
调用上面的类
sunClass(18,"鲁梦瑶").also{
println(it.writeline())
}.also{
println(it.writeLine())
}
类属性,给类属性赋值,使用field
// 面向对象,给属性赋值
class AttributeClass{
// 自定义属性访问器
var name:String = ""
set(value){
field = value
}
get() = field
// 属性访问
var age:Int = 0
set(value) {
field = value
}
get() = field
}
可见性修饰符
public class{}
// 仅内部可用
private class{}
// 子类可用
protected class{}
// 相同module可用
internal class{}
延迟初始化,lateinit
// 延迟初始化
class lateinitClass{
lateinit var name:String;
// 初始化name值,只有在初始化后才能使用name
fun ready(){
name = "延迟初始化变量,必须初始化后才能使用";
}
fun battle(){
// 使用isInitialized判断name是否被初始化
if(::name.isInitialized)
println(name)
}
}
惰性加载
// 延迟加载,惰性初始化
// 只有在调用该变量时才会初始化
//
class byLazy{
val lazyConfig by lazy{
loadConfig()
}
fun loadConfig():String{
return "惰性加载";
}
}
is 和 as
// 使用 is 判断 是否某个类型
var a = "";
a is String
// 使用as 强制转换
open class a{}
class b :a(){}
val b = b();
// 把子类转为父类,
b as a;
不安全的转换
// 无法转换
var a :String = b as String;
// null 不能转换为 string
var a:String? = b as String?
安全转换
var a:String? = b as? String
与C#的 as 不同
// kotlin 的as 无需再次赋值,比如
(b as a); // 之后调用b即可
// c#如下, 需要使用新的对象赋值
var x = (b as a);
Any是所有 类的超类
相当于C#的object
// Any
fun anyclass(name:Any){
println(name is String)
}
匿名对象,objcet
open class objectTest {
open fun load(){
println("我是原生对象")
}
}
fun mian(){
// 匿名对象继承 objectTest
var overrideObject = object:objectTest(){
override fun load(){
println("我是一个对象,继承 objectTest类")
}
}
overrideObject.load()
}
声明一个对象
var objectCreated = object{
val name = "jack";
val age = 18;
}
println(objectCreated.name)
companion半生对象,像是其他语言的static
class companionClass{
companion object{
var config = "null";
fun load(_config:String){
config = _config
}
fun default(){
println(config)
}
}
}
// 调用
companionClass.load("config已经加载")
companionClass.default();
data class 数据类
// 数据类必须有最少一个参数
// 数据类,仅提供数据,比如获取的json,xml等需要赋值的类
data class dataClass(var x:Int,var y:Int) {
override fun toString(): String {
return "dataClass(x=$x, y=$y)"
}
}
复制 data class
val data =dataClass(30,12)
var dataClassCopy = data.copy()
println(dataClassCopy)
operator - 运算符重载,类本身不支持 + += - -=
但是可以重载运算符
class operatorClass(var max:Int,var min :Int) {
// 重写 plus 方法
operator fun plus(other:operatorClass) = operatorClass(max + other.max,min + other.min)
override fun toString(): String {
return "operatorClass(max=$max, min=$min)"
}
}
// 调用
(operatorClass(1,6) + operatorClass(23,64)).also{ println(it.toString())}
enum 枚举
enum class enumClass{
东,
南,
西,
北
}
初始化枚举
enum class enumClass(val value :Int) {
东(1),
南(2),
西(3),
北(4)
}
// 调用
enumClass.南.also { println(it.value) }
枚举方法
enum class enumClass(val value :Int) {
东(1),
南(2),
西(3),
北(4);
fun plus() = value +1;
}
// 调用
enumClass.南.plus().also(::println)
sealed - 密封类,某种意义上来说是enum的拓展
sealed class sealedClass {
object error:sealedClass();
class success(val notify:String):sealedClass();
}
// 使用 sealed
class sealedUse(var value:sealedClass){
fun mian(){
// when语句判断value的类型,然后做出相应动作
val status = when(value){
// 如果 = erro
is sealedClass.error ->"失败"
// 如果 = success
is sealedClass.success -> (value as sealedClass.success).notify
}
println(status)
}
}
泛型
// 泛型
class fanClass<T> (var age:T){
init{
println(age)
}
// 再次声明一个泛型
// 泛型函数
fun <R> create(value :()->R) : R{
return value();
}
}
class createFan{
fun mian(){
val fan:fanClass<Int> = fanClass(18)
// 他的返回值是一个泛型lambda,而lambda如果是最后一个参数可以用括号代替()
val fanRtrun = fan.create{
fan.age * 361
}
}
}
多参数vararg, C#里面的param
// 多个参数
class paramListClass<T>(vararg var listName:T) {
// 用泛型给array赋值时必须加 out
val listParam :Array<out T> = listName;
//
fun mian(index:Int):T{
return listParam[index];
}
}
// 调用
paramListClass(435,345,346,236,46,6).run{
for( item in 0 .. 5)
mian(item).also(::println)
}
协变 out, 逆变in
公式:
协变:IFoo<父类> = IFoo<子类>;
逆变:IBar<子类> = IBar<父类>;
协变 逆变在array中使用
// 协变和逆变
class UseArray<T>{
// 插入使用 in , 访问使用 out
// 父继承子类使用out,子类继承父类使用in
val list:Array<in T> = Array(5){};
fun mian(set:T){
list[0] = set;
println(list[0])
}
}
// 调用;
UseArray<String>().also{
it.list[1] = "String2";
it.list[2] = "String3";
it.list[3] = "String4";
it.list[4] = "String5";
}.also{
it.mian("第一个String")
}
判断 泛型类型 reified , 使用reified必须使用 inline
class reifiedClass<T> {
// reified 必须是 内联函数(inline)
inline fun <reified T> createOrRandow(create:()->T):T{
val list = listOf(
dog("dock",1),
man("jack",0)
)
// @shuffled 洗牌
val random = list.shuffled()?.firstOrNull();
// 判断是否 指定类型,如果是则为true,否则使用自定义lambda
return if(random is T){
random;
}else{
create();
}
}
}
open class Hub{
}
class dog(var name:String, var age:Int):Hub(){
override fun toString(): String {
return "dog(name='$name', age=$age)"
}
}
class man(var name:String, var status:Int):Hub(){
override fun toString(): String {
return "man(name='$name', status=$status)"
}
}
// 调用上面的类
class useReified{
//
fun mian(){
reifiedClass<Hub>().createOrRandow {
man("Tom",3)
}.run{
toString().run(::println)
}
}
}
函数式接口 fun interface
class funInterface{
/*
* 函数式 接口
* */
fun interface isCode{
fun invoke():String;
}
fun mianLambda(){
// 使用lambda调用函数式接口
val createCode = isCode{
"函数式接口,使用lambda调用"
}
createCode.invoke().run(::println)
}
// object 调用
fun mianVal(){
val createCode = object:isCode{
override fun invoke():String{
return "函数式接口,object调用"
}
};
createCode.invoke().run(::println)
}
}
拓展函数
class expandFun {
// companion,伴生对象,等同于其他语言的static
companion object{
}
}
// 拓展函数
fun expandFun.mian(){
println("拓展函数")
}
// 给companion添加拓展函数
fun expandFun.Companion.load(){
println("给 companion添加拓展函数")
}
// 泛型拓展
// 拓展后所有类型都具有 ExpandFun
fun <T> T.ExpandFun(){
println("泛型拓展函数")
}
// 可空拓展函数
// 这里的 可空类型是会执行的
/*
* 这里不会执行
* val a :String = null;
* a?.IsNullToNotify();
* */
fun String?.IsNullToNotify() = this ?: "null";
inner 内部类
// 内部类
class innerClass {
var studio = "visual studio ";
inner class innerSun{
fun load(){
// inner(内部类),可用调用上级的属性、方法
println(studio)
}
}
}
委托类 使用 by关键字
// 定义一个接口
interface BaseInterface{
fun ToString():String;
fun ToInt():Int;
}
// 定义一个类,用于实现BaseInterface
class useBaseInterface:BaseInterface{
override fun ToString(): String {
return "ToString Method";
}
override fun ToInt() = 666;
}
// 委托, 把 BaseInterface 赋值给变量 B
class delegate(var B:BaseInterface):BaseInterface by B {
}
// 调用, 先声明一个已经实现BaseInterface的类
val baseTo = useBaseInterface();
// 使用该类作为参数,即可调用BaseTo实现的方法
delegate(baseTo).ToString().run(::println)
delegate(baseTo).ToInt().run(::println)
懒加载,lazy配合 委托使用
// 几种懒加载实现
// 委托实现懒加载
class delegateAndLazy {
val load by lazy{
"字符串类型"
}
val loadTwo :String by lazy{
"字符串类型"
}
val loadThree = lazy{
"字符串类型"
}
}
// 调用
delegateAndLazy().also{
it.load.run(::println);
it.loadTwo.run(::println)
it.loadThree.run{
println(value)
}
}
委托, 映射类,通过字符串键属性名称
// 映射类
class myMap(val map:Map<String,Any?>){
// 通过字符串键 属性名称
val name:String by map
val age:Int by map
}
// 调用
myMap(mapOf("name" to " 当前字符串赋值给name,name的值","age" to 1)).let{
println(it.age)
println(it.name)
}