Kotlin 是一门现代但已成熟的编程语言,旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作,并提供了多种方式在多个平台间复用代码,以实现高效编程。Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrains 设计开发并开源。 Kotlin 可以编译成Java字节码,也可以编译成 JavaScript,方便在没有 JVM 的设备上运行。 在Google I/O 2017中,Google 宣布 Kotlin 成为 Android 官方开发语言。
1.内置数据类型 1.基本类型
String 字符串
Char 字符
Boolean 布尔
Int 整型
Double 浮点数
List 集合
Set 无重复的元素集合
Map 键值对的集合
1 2 3 fun main{ var name:string = "Array" }
val ===> 不可改变相当于js的readonly
1 2 3 fun main{ var name:string = "Array" }
const val====>编译时常量 修饰符const不能修饰局部
只能在函数之外定义
1 2 3 4 const val PI = 3.1415 fun main{ var name:string = "Array" }
2.数字类型
Byte
Short 短整型
Int 整型
Long 长整型 可以用_表示,计数 100_000_000
1 2 var n1:Long =10L var n2:Long =100_000_000
UByte
UShort
UInt
ULong
无符号 在后面加上u或U和长整型类似
1 2 3 var n3:UInt = 123uvar n4:UInt = 123Uvar n5:ULong = 123UL
Float
Double
默认为Double类型,如果要使用float要加上f或者F
1 2 3 var m1:Float = 1.12F var m2:Double = 1.12 var m3:Float = 1.12f
3.Boolean类型
0,false,null为假,其他为真
&& || !
4.字符类型
使用.code获取ascII码
\u转义成字符(unicode编码)
1 2 3 4 5 val c1:Char = 'a' println(c1.code) val c2:Char ='\u2C77' println(c2)
5.字符串
用三引号包括字符串=>原始字符串
.trimIndent()去掉空格
$变量名 格式化字符串
1 2 3 4 5 6 7 val s2:String = """ aha sjs dld kjl """ .trimIndent()println(s2)
1 2 3 val s3:String = "$PI1 圆" println(s3) val s3:String = "${PI1} 圆"
6.运算符 与 and 或or 异或xor
shl 左移位 shr 右移位 ushr无符号右移位
2.条件语句 1.when 类似 switch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 when (c) { 1 -> { println("1" ) } 2 -> { println("2" ) } 3 -> { println("3" ) } else -> { println("0" ) } }
2.for循环 ..区间运算符20..100相当于 20 <= a <= 100
1 2 3 4 5 6 7 8 val Range1 = 5. .10 val Range2 = 5. .10 for (i in Range1 step 2 ){ println(i) } for (i in 10 DownTo 1 ){ println(i) }
3.函数
函数可以嵌套使用即函数内部声明函数,在函数内部声明的函数只能在函数内部调用,并且可以使用嵌套该函数的函数体内的变量
1 2 3 4 5 6 7 8 9 10 11 fun main () { outer() } fun outer () { val value = 10 fun inner () { println(value) } inner () }
message:String指定形参类型
():unit指定返回值类型 unit相当于void即无返回值(可以省略不写)
1 2 3 fun test (message:String ) :Unit { println(message) }
设置默认值
1 2 3 4 5 fun test1 (a:Int =3 ,b:Int =6 ) :Int { return a+b } test1(b=9 )
简洁写法 返回值为a+b
1 fun test2 (a:Int ,b:Int ) = a+b
引用函数
1 2 3 4 5 6 7 8 fun main () { val test2 = ::test1 test2() } fun test1 () { println("hahha" ) }
4.变量作用域 1.get set
1 2 3 4 5 6 7 8 9 10 var v:Int = 10 get () = field * 100 set (value) { println("赋值" ) field = 12 } fun main () { println(v) }
5.常用库函数
var value1 = readln()
相当于Java的Scanner
1 2 3 4 5 6 7 8 9 10 println(2.0 .pow(4 )) println(abs(value2)) println(min(10 ,20 )) println(max(10 ,20 )) println(sqrt(9.0 ))
1 2 3 4 5 6 7 8 9 10 11 12 println(Math.E) println(Math.PI) println(sin(0.5 *Math.PI)) println(cos(0.5 *Math.PI)) println(tan(Math.PI)) println(asin(1.0 )); println(acos(1.0 )); println(atan(1.0 ));
5.函数类型变量 1.()-> 1.()括号里为参数类型 ->后为返回值类型
1 2 3 4 5 6 7 8 9 10 11 12 fun main () { val fun1:(Int )->String = outer("Hello" ) val name = fun1(10 ) println(name) } fun outer (name:String ) :(Int )->String{ return fun (number:Int ) :String{ return number.toString()+"个" +name } }
2.可以嵌套使用
1 2 3 fun fu1 (n1 :Int ,n2 :Int ):((String )->String ,String ) -> String { }
2.lamda表达式 1 2 3 4 5 val func1:(String)->Int = { println(it) 10 }
1 2 3 4 5 6 var func:(String,String)->Int = { a,b -> println(a) println(b) 10 } println(func("1" ,"2" ))
尾随lamda
1 2 3 4 5 6 7 8 9 10 fun main () { test{ println(it) 10 } } fun test (func:(String )->Int ) { println(func("Hello" )) }
小实验
1 2 3 4 5 6 7 8 9 10 11 12 val v1 = fu1(10 ,20 )val f1 = v1("Hello" ){ "1" } println(f1) fun fu1 (n1:Int ,n2:Int ) :(String,(String)->String) -> String{ println(n1+n2) return fun (s2:String , fun2:(String )->String ) :String{ return fun2("1234" )+s2 } }
如果函数调用的是尾随的lamda则标签名字就是函数的名字
1 2 3 4 val fun2:(Int ) -> Int = mytest@ { if (it >10 ) return @mytest 10 20 }
3.内联函数 1.声明内联函数
编译之后将函数原封不动加入到调用的位置
1 2 3 inline fun mytest () = { println("1" ) }
高阶函数使用lamda
内联高级函数的lamda参数可以直接写return不指定标签
1 2 3 4 5 6 7 8 9 10 11 fun main () { mytest { return } println("Hi" ) } inline fun mytest (func: (String ) -> Int ) :Unit { println("1" ) func("2" ) }
在不需要内联的函数形参上添加noinline关键字,可以防止函数调用内联
标签可以指定为外部的函数名称
6.类和对象 1.类的创建
var 可改
val 不可改
1 2 3 class Student constructor (var name:String,val age:Int ){ }
如果在类中定义,要赋值
1 2 3 4 class Student { var name:String = "Jack" var age:Int = 18 }
1 2 3 4 class Student (name:String,age:Int ) { var name:String = name var age:Int = age }
懒加载,在使用之前必须初始化
1 2 3 4 class Teacher { lateinit var name: String lateinit var age:Integer }
2.对象的创建 1 2 3 4 5 6 val s1 = Student("Jerry" ,44 );println(s1.age) println(s1.name) s1.name = "Tom" println(s1.name)
constructor
当类有主构造函数是,其他次要构造函数都要调用主构造函数
主构造函数可以省略constructor不写
1 2 3 4 5 class Student1 (var name:String,var age:Int ){ constructor (name:String):this (name,90 ) }
1 2 3 class Student1 { constructor (name:String) }
3.对象的初始化
在创建对象时会执行init里的代码
可以写多个init 相当于主构造函数的函数体
1 2 3 4 5 class Teacher1 (var name:String,var age:Int ){ init { println("创建成功" ) } }
4.基本数据类型常用方法 1 2 3 4 5 6 7 8 9 10 11 val v1:String = "10" println(v1.toInt()) val v2:String = "samll" println(v2.uppercase()) val v3:String = "BIG" println(v3.lowercase()) val v4:String = "how are you" println(v4.replace('o' ,'m' )) println(v4.length)
5.运算符重载
重载二元运算符 +
1 2 3 4 5 class Student constructor (var name:String,var age:Int ){ operator fun plus (another:Student ) :Student{ return Student(this .name+another.name,another.age+this .age) } }
重载一元运算符 !
1 2 3 operator fun not () :Student{ return Student(this .name.reversed(),this .age) }
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a– a.dec()
a++ a.inc()
1 2 3 4 5 6 7 operator fun inc () :Student{ return Student(name,age++) } operator fun dec () :Student{ return Student("name" ,age++) }
a+=b a.plusAssign(b)
a-=b a.minusAssign(b)
a*=b a.timesAssign(b)
a/=b a.divAssign(b)
a%= b a.remAssign(b)
同时定义+和+=可能会产生歧义
a>b a.compareTo(b) >0
a<b a.compareTo(b) <=0
a>=b a.compareTo(b) >0
a<=b a.compareTo(b) <=0
() invoke
6.中缀函数
println(10 shl 2) 左移位
调用可以省略点和括号
要求:
1.必须是成员函数
2.只能有一个参数
3,参数不能有默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Student constructor (var name:String,var age:Int ){ operator fun plus (another:Student ) :Student{ return Student(this .name+another.name,another.age+this .age) } operator fun not () :Student{ return Student(this .name.reversed(),this .age) } operator fun inc () :Student{ return Student(name,age++) } operator fun dec () :Student{ return Student("name" ,age++) } infix fun test (string:String ) :String{ return name+string } } package demo2fun main () { val stu = Student("zs" ,11 ) println(stu test "hahaha" ) println(stu.test("hahaha" )) }
7.空值和空类型
当我们直接给一个变量赋值空null是kotlin在编译阶段就会报错
加上?:表明这是一个可空的类型
加上!!强制调用
安全访问方法
1 2 3 val s:Student? = null val a = s?.getdata() ?: "hahah" println(a)
?: 类似与三元运算符 ,当对象为空是会执行?:右边的函数
8.解构
component1即为第一个解构的参数
解构()里的变量名可随意取
1 2 3 4 5 6 7 8 9 10 11 12 13 class Car (var name:String,var price:Int ) { operator fun component1 () = name operator fun component2 () = price } fun main () { val car:Car = Car("ll" ,1000 ) val (a,b) = car println(a) println(b) val (_,b) = car }
应用-》在lamda表达式中使用
1 2 3 4 val func1:(Car)->String = { (a,b) -> a+b.toString() } println(func1(car))
7.类与继承 1.权限声明
public
private
protected
internal 只能在当前项目内访问,当别人引用我们的项目时,不能使用
2.类的继承
声明继承
被继承的类要要声明open
1 2 3 4 5 6 7 8 public open class Car (internal var name:String, public var price:Int ) { operator fun component1 () = name operator fun component2 () = price } public class SuperCar :Car ("1" ,1000 ){ }
1 2 3 4 5 6 7 8 public open class Car (internal var name:String, public var price:Int ) { operator fun component1 () = name operator fun component2 () = price } public class SportCar (name:String,price: Int ):Car("1" ,1000 ){ }
当子类未声明主构造函数
1 2 3 4 5 6 7 8 public open class Car (internal var name:String, public var price:Int ) { operator fun component1 () = name operator fun component2 () = price } public class SportCar :Car { constructor (name:String,price: Int ):super ("1" ,1000 ) }
3.方法的重写(覆盖)
可以通过super关键字调用父类的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 public open class Car (internal var name:String, public var price:Int ) { operator fun component1 () = name operator fun component2 () = price open fun run (data :String ) { println(data +"1" ) } } public class SuperCar :Car ("1" ,1000 ){ override fun run (data : String ) { super .run(data ) } }
重写成员变量
1 2 3 4 5 6 7 public open class Car () { open var name:String = "zs" } public class sportcar : Car (){ override var name: String = "ls" }
4.顶层Any类
相当于java的Object
=== 判断是否是同一个引用对象
5.抽象类 1 2 3 4 5 6 7 8 9 10 abstract class annimal { abstract var name:String abstract fun say () } class cat (override var name: String) :annimal(){ override fun say () { println("miao" ) } }
1 2 3 4 5 6 7 8 9 10 11 abstract class annimal { abstract var name:String abstract fun say () } class cat :annimal (){ override var name:String = "cat" override fun say () { println("miao" ) } }
6.接口
接口的所有成员变量和类方法都是抽象的,因此可以省略abstract不写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 interface A { val name:String fun run1 () :String } interface B { val age:Int fun run2 () :String } class stu () :A,B{ override val age: Int = 16 override val name: String ="NAME" override fun run1 () : String { return "1" } override fun run2 () : String { return "2" } }
接口也可以实现默认方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 interface A { val name:String fun run1 () :String } interface B { val age:Int fun run2 () :String = "AGE" } class stu () :A,B{ override val age: Int = 16 override val name: String ="NAME" override fun run1 () : String { return "1" } override fun run2 () : String { return "2" } }
如果继承的两个接口有重复函数可以使用<>消除歧义
1 2 3 4 5 6 7 8 9 10 11 12 interface A { fun run () :String = "NAME" } interface B { fun run () :String = "AGE" } class stu () :A,B{ override fun run () : String = super <A>.run(); override fun run () : String = super <B>.run(); }
7.类的扩展 1 2 3 4 5 6 7 8 9 10 11 class animal { fun test () { println("HAHAHA" ) } } fun animal.test () = println("HELLO" )fun main () { animal().test() }
当有重复函数是扩展会失效
添加属性,此时field无法使用
类的扩展会受到访问权限的影响
1 2 3 4 5 var animal.NAME: String get () = "" set (value){ println("SET" ) }
在扩展的函数中可以直接使用类的成员变量,可以不使用this关键字
1 2 3 4 5 6 class animal { val name:String = "JKL" } fun animal.test () = { println(name) }
指定调用的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class A { fun hello () { println("Hello" ) } } class B (private val a:A){ fun A.test () { hello() this .hello() this @B .hello() } fun hello () { println("HELLO" ) } }
将一个扩展函数作为参数传递到一个函数类型变量,在具体操作前要增加类型名称
1 2 3 4 5 6 7 fun main () { val func:String.() -> Int = { this .length } println("hahahahhaha" .func()) println(func("hello" )) }
8.范型 1.范型
可以直接接收数值,自动转换类型
1 2 3 4 5 6 7 class Score <T >(var name:T){ } fun main () { val stu = Score("123" ) }
2.官方高阶扩展函数
apply 传入一个lambda表达式,也就是我们要如何操作这个对象
let 执行一个lamda表达式并将得到的结果作为返回值
also 与apply类似
run 与let类似
1 2 3 4 fun main () { val a:Any = Any() a.apply { } }
3.协变和逆变 1 2 3 4 5 6 class Num <T >(var name:T)fun main () { val v1:Num<Int > = Num<Int >(1 ) val v2:Num<Number> = v1 }
虽然Number是Int的父类但是缺类型不匹配
协变 父类接收子类
逆变 子类接收父类
抗变 类型不相关Test<Int>与Test<Number>无关
使用out开启协变,使用in开启逆变
1 2 3 4 5 6 7 class Num <T >(var name:T)fun main () { val v1:Num<Int > = Num<Int >(1 ) val v2:Num<out Number> = v1 }
1 2 3 4 5 6 7 class Num <T >(var name:T)fun main () { val v1:Num<Any> = Num<Any>(1 ) val v2:Num<in Number> = v1 }
可以使用*来代指任意类型
4.范型的界限
限制范型的类型
1 2 3 4 5 6 7 class Num <T : Number >(var name:T)fun main () { val v1:Num<Int > = Num<Int >(1 ) val v2:Num<out Number> = v1 }
1 2 3 4 class Num <T >(var name:T) where T:C,T:D open class C open class D
也可以直接在类或接口的参数中声明
1 2 3 interface Test <out T >{ fun test () :T }
5.类型擦除
内联函数的类型擦除与普通函数的
reified通过该关键字具化类型
1 2 3 4 5 6 7 8 inline fun <reified T> test (value:Any ) :Boolean { return value is T } fun main () { val result = test<String>("1" ) println(result) }
9.数组 1.定义和遍历数组 1 2 3 4 5 6 fun main () { val array:Array<Int > = arrayOf(1 ,2 ,3 ,4 ,6 ,5 ) for (element in array){ println(element) } }
获取长度 array.size
数组在创建完成后数组容量和元素类型是固定不变的后续无法修改
1 2 3 4 5 6 7 8 9 fun main () { val array:Array<Int > = arrayOf(1 ,2 ,3 ,4 ,6 ,5 ) for ((index,element) in array.withIndex()){ println(array[index]) println(index) println(element) } }
数组的创建和使用
1 array.forEach { println(it) }
1 2 println(array.joinToString("," ,"[" ,"]" ))
1 2 val array:Array<String> = Array(5 ){"1234" }
2.数组的操作
==号判断内容是否相同
1 2 3 val array1:Array<String> = Array(5 ){"1234" }val array2:Array<String> = Array(5 ){"1234" }println(array1.contentEquals(array2))
拷贝数组
可以指定参数,为拷贝的数量如果数量大于数组大小会用空填充
1 2 3 4 var array3:Array<String> = array2.copyOf()var array4:Array<String> = array2.copyOfRange(2 ,3 )
分割数组
1 var array5:Array<String> = array2.sliceArray(1. .3 )
数组可以用加号进行合并
判断指定元素在不在数组
1 2 array2.contains("1234" ) "1234" in array2
快速查找元素在哪一位置
reversedarray反转数组
sort排序 sortDesc倒排序
可以重写一个类的compareTo方法指定排序规则
1 2 3 4 5 class B ():Comparable<B>{ override fun compareTo (other: B ) : Int { return B.age - A.age } }
vararg 可以接收任意个同类型的参数
3.基本数组类型 1 2 3 4 5 6 7 8 9 Kotlin Java ByteArray byte[] CharArray char[] ShortArray short[] IntArray int[] LongArray long[] DoubleArray double[] FloatArray float[] BooleanArray boolean[]
4.List
可变的列表,可以插入和删除
1 2 3 4 5 6 7 8 fun main () { val list:MutableList<String> = mutableListOf("1" ,"2" ,"3" ); list.add("4" ) list.add(1 ,"5" ) list.remove("1" ) list.removeAt(1 ) println(list) }
不可变的列表,无法插入删除
1 val list1:List<Int > = listOf(1 ,2 ,3 )
可以用{}进行初始化赋值
使用for in 进行遍历
1 2 3 4 val list2:List<Int > = List<Int >(3 ){10 }for (ele in list2){ println(ele) }
5.Set
没有重复元素,可用于去重
不能在指定位置插入
1 2 3 var set :MutableSet<Int > = mutableSetOf(1 ,2 ,3 )println(set .elementAt(0 ))
集合的运算
1 2 3 4 5 6 7 8 println(set1 union set2) println(set1 + set2) println(set1 intersect set2) println(set1 - set2) println(set1 subtract set2)
不同类型的set
1 2 3 4 val set1:SortedSet<Int > = sortedSetOf(9 ,5 ,3 ,19 ) println(set1) val set2:HashSet<Int > = hashSetOf(1 ,2 ,3 ) println(set2)
6.Map
Pair
1 val pair:Pair<Int ,String> = 10001 to "zs"
创建Map
map[键]获取值
1 2 3 4 val map:MutableMap<Int ,String> = mutableMapOf( 1001 to "zs" , 1002 to "ls" )
1 2 3 4 println(map.keys) println(map.values)
遍历
for in
for each
1 map.forEach{(k,v) -> println(k.toString()+v) }
可以直接+=添加新键值对
键不能重复,否则数据会被覆盖
7.迭代器 1 2 3 4 5 val iterator:Iterator<String> = array1.iterator()println(iterator.next()) println(iterator.next()) println(iterator.next()) println(iterator.next())
遍历数组
1 2 3 4 val iterator:Iterator<String> = array1.iterator()while (iterator.hasNext()){ println(iterator.next()) }
ListIterator可以实现双向遍历
MutableIterable迭代器 可以在遍历的时候进行删除
8.数组的扩展操作
map 类似于js的map对每一个元素进行操作并且返回一个值
1 2 3 val list:MutableList<String> = mutableListOf("AAA" ,"BB" ,"DDD" )val list2 : MutableList<Int > = list.map { it.length }.toMutableList()println(list2.joinToString())
遍历map
1 2 3 4 5 6 7 val map:Map<String,Int > = mapOf( "AAA" to 1 , "BB" to 2 , "CCCC" to 3 ) val map1: Map<Int , Int > = map.mapKeys { it.key.length }val map2 : Map<String,String> = map.mapValues { it.value.toString() }
zip
unzip
1 2 3 4 val zipmap: List<Pair<String, Int >> = list1.zip(list2)println(zipmap) val pair:Pair<List<String>, List<Int >> = zipmap.unzip()println(pair)
associate将列表映射为一个map集合
1 2 val associates : Map<String,Int > = list1.associate { it to it.length }println(associates)
扁平化处理多维数组
1 2 3 4 val array= Array(10 , {Array(10 ){0 }}) val list = List(10 ,{List(10 ){0 } })println(array.flatten())
array.flatMap { }在遍历的同时映射
filter过滤操作
1 2 3 list1.filter { it >= 10 } list1.filterNotNull()
10.序列
在使用时才会执行其中的语句
1 2 3 4 5 6 val sequence:Sequence<Int > = generateSequence { println("构造" ) 10 } println(sequence.iterator().next())
普通的list,在执行操作时就会调用函数
1 2 3 4 5 6 7 8 9 val list:List<String> = mutableListOf("AAA" ,"BB" ,"CCC" ,"dd" ,"EEE" ,"FF" )val result = list.filter { println("执行1" ) it.length > 2 }.map { println("执行2" ) it.lowercase() }.take(2 ) println(result)
进行优化,在调用使用的时候才会执行内部
数据量庞大时推荐使用
1 2 3 4 5 6 7 8 9 val list:List<String> = mutableListOf("AAA" ,"BB" ,"CCC" ,"dd" ,"EEE" ,"FF" )val result = list.asSequence().filter { println("执行1" ) it.length > 2 }.map { println("执行2" ) it.lowercase() }.take(2 ) println(result.joinToString())
11.特殊的类型 1.数据类型
本质是class
1 2 3 data class Data (val name:String,val age:Int ){ }
加上data关键字后
自动生成.equals()/.hashCode()
.toString()
.componentN()
.copy()方法
数据类不能是抽象类
主构造函数必须有一个参数
主构造函数变量必须是var或者val
编译器只会根据构造函数生成,因此可以将参数移出主构造函数,equals方法就不会考虑到写在主构造函数之外的变量
2.枚举类型
加上enum关键字
枚举类可以重写内部的抽象函数,当继承了一个接口时,可以在每个枚举类中重写,或者在定义枚举类的类中重写
1 2 3 4 5 6 7 fun main () { println(Status.ERR.code) } enum class Status (var code:String){ ERR("0" ),SUCC("1" ),COMP("2" ) }
可以定义成员函数
1 2 3 4 5 6 7 8 9 10 11 fun main () { val status = Status.ERR println(status.code) println(status.isERR()) } enum class Status (var code:String){ ERR("0" ),SUCC("1" ),COMP("2" ); fun isERR () = this == ERR }
定义成员变量
1 2 3 4 5 6 7 8 9 fun main () { println(status.state) } enum class Status (var code:String){ ERR("0" ),SUCC("1" ),COMP("2" ); val state:Int = 10 }
使用when
1 2 3 4 5 6 val message:String = when (status){ Status.ERR -> "错误" Status.SUCC -> "成功" Status.COMP -> "运行" } println(message)
entries获取整个枚举类
1 2 val statuslist = Status.entriesprintln(statuslist.joinToString())
12.匿名类 1.匿名类
使用object关键字声明匿名类,并且可以用变量接收
1 2 3 4 5 6 7 8 9 fun main () { val stu = object { fun test () :String{ return "123" } } val message = stu.test() println(message) }
如果接口只有一个函数,可以采用简洁写法实现匿名类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fun interface Krunnerable{ fun test () } fun main () { val stu = object { fun test () :String{ return "123" } } val message = stu.test() println(message) val runnerable = Krunnerable{ println("1234" ) } }
单例对象
1 2 3 4 5 6 7 8 9 10 11 object Run{ 通过objext关键字 val name:String = "name" override fun toString () : String { return super .toString() } } fun main () { val run = Run println(run.toString()) }
2.伴生对象
companion
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Animal (val name:String){ companion object Cat{ val age:Int = 90 fun test () { println("test" ) } } } fun main () { Animal.test() }
13.委托模式
使用by关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 interface Base { fun test () } class BaseImpl ():Base{ override fun test () { println("test" ) } } class Work (val base:BaseImpl) : Base by base fun main () { val work = Work(BaseImpl()) work.test() }
使用预设代理lazy在调用时赋值
1 2 3 4 5 6 7 class Exe (){ val per:String by lazy { "geren" } } fun main () { val message:String = Exe().per println(message) }
属性可以委托属性代理
1 2 3 class Exe1 (val name:String){ val per:String by ::name }
设置观察者
1 2 3 4 5 6 class Exe2 (val name:String){ val per:String by Delegates.observable("初始值" ){ prop,new,old -> println("属性值为${prop} ,新值为${new} ,旧值为${old} " ) } }
14.密封对象
sealed class A
不能在外部继承使用以及实例化(模块内部)
密封类是可以被继承的,密封类的子类也可以是密封类
15.异常机制 1.异常的定义 1 2 3 4 Exception in thread "main" java.lang.ArithmeticException: / by zero at demo1.Test5Kt.div(test5.kt:47) at demo1.Test5Kt.main(test5.kt:42) at demo1.Test5Kt.main(test5.kt)
自定义Exception
1 2 3 4 5 6 class myException (override val message: String?):Exception(message)private fun div (x:Int , y:Int ) :Int { if (y==0 ) throw myException("div by zero" ) return x / y }
2.捕获异常 1 2 3 4 5 6 7 val array:MutableList<Int > = mutableListOf(1 ,2 ,9 )try { println(array[3 ]) }catch (e:IndexOutOfBoundsException){ e.printStackTrace() } println("after" )
多个catch
1 2 3 4 5 6 7 8 val array:MutableList<Int > = mutableListOf(1 ,2 ,9 )try { println(array[3 ]) }catch (e:IndexOutOfBoundsException){ e.printStackTrace() }catch (e:Exception){ e.printStackTrace() }