kotlin目前是android第一开发语言
优点:简洁 空值安全 100%兼容java 函数式编程 协程 DSL
开发工具:idea as eclipse
kotlin文件的后缀是: .kt
main函数是程序的入口
基本数据类型:Boolean Byte Char Short int Float Double Long
智能类型判断:自动选择使用java的基本数据类型
kotlin类型类型安全
高精度:BifDecimal
var big:BigDecimal=BigDecimal(val"0.1212121212112")
var:可变变量
val:不可变量(与java的final修饰的变量类似)
删除空格 : .trim()
删除空格前导 : .trimMargin(marginPrefix:"")
字符串比较: 字符串1 = = = 字符串2(=== 比较字符串引用地址)
元祖数据:
二元元祖 Pair 保存2个数据
三元元祖 Triple 保存3个数据
val pair:Pair<String,Int>=Pair("ada",20)
//pair.first 取第一个数据
空值处理:
String : 非空类型
String? : 可空类型
?. : 空安全调用符号 ,如果为空不执行后面的代码
!!. : 非空断言(一定不为空,如果为空,还是会报错)
控制台输入函数 readLine()
控制台输出println()
函数(程序执行的片段):fun修饰
1.无参数,无返回值
2.有参数,无返回值
3.无参数,有返回值
4.有参数,无返回值
字符串模版: $ 站位符
for循环:
val s="asdasdasdasd"
for(a:Char in s){
}
s.forEach(){
printin(it)
}//it是每个元素
//加上index角标的for循环
for ((index,c) in s.withIndex()) {
println("index=$index c=$c")}
s.forEachIndexed{ index, c-> }//角标 index 元素 c
break:跳出循环
continue:跳出本次循环
return:结束方法
loop:标签处返回
loop@for(){ //loop可以使任意字符
for(){
if(){
break@loop
}
}
}
do while
while
区间:
var r:IntRange=1…100 //1到100
var r=IntRange(1,100)
var r:IntRange=1 until 100 //1到99
IntRange LongRange CharRange(字符区间(a..z))
反向区间 1.val r:IntProgression=10 downTo 1
2.val r2:IntProgression=r.reversed() //区间反转
if:return if (a > b) a - b else b - a
list:
例如: var lists=listOf("121","12312")
for((i,e) in lists.withIndex()){
println("$i $e") //i是索引 e是元素
}
map:
例如 :var map=TreeMap<String,String>()
map["hao"] ="good"
println(map["hao"])
数组:
例如:var a=arrayof(12,3,4);
var a= IntArray(10) //定义元素个数为10个的Int数组
val intArr = IntArray(10){ 0} //定义了一个长度为10的Int数据类型并且所有元素都为0
数组循环
for (s in array) { println(s)}
array.forEach { println(it)}
for循环遍历元素以及角标
for ((index,s) in array.withIndex()) { println("角标$index s=$s")}
array.forEachIndexed { index, s -> println("角标=$index 元素=$s")}
修改某一个位置上的元素
newArr[0] = 20 //将角标0元素值设置为20
newArr.set(4,20)//将角标4元素值设置为20
查找第一个元素2
第一种:
arr.indexOf(2)
第二种:
arr.indexOfFirst {it==2 }
查找最后一个元素2
第一种:
arr.lastIndexOf(2)
第二种:arr.indexOfLast { it == 2 }
When:多分支选择,加强版的switch
基本表达式:when (age) {
7 -> return "开始读小学"
12 -> { println("开始读中学") return "开始读小学" }
else -> return "读社会大学“}
加强版:when(ele){
10-> println("它10岁") is Int-> println("传递的是年龄")
in 1..10-> println("在10岁以内")
!in 1..10-> println("不在10岁以内")
else-> println("所有情况都不满足")}
表达式不带参数: when{
ele == 10-> return "它十岁"
ele is Int-> return "传递的是年龄"
ele in 1..10->return "在10岁以内"
ele !in 1..10-> return "不在10岁以内"
else-> return "所有情况都不满足“}
表达式返回值:val s = when {
ele == 10 -> "它十岁"
ele is Int -> "传递的是年龄"
ele in 1..10 -> "在10岁以内"
ele !in 1..10 -> "不在10岁以内"
else -> "所有情况都不满足“}
函数表达式:
fun add(a:Int,b:Int):Int{ return a+b}
函数体只有一行,可以简写
fun add(a:Int,b:Int):Int = a+b
还可以更加简洁
fun add(a:Int,b:Int) = a+b
定义函数变量保存函数引用
val addFun1:(Int,Int)->Int = ::add
执行这个函数
第一种: addFun1(10,20)
第二种: addFun1.invoke(10,20)
定义函数变量时定义函数(这个函数也是求a+b的和)
var addFun:(Int,Int)->Int={a,b->a+b }
执行这个函数
第一种:val result = addFun(10, 20)
第二种:val result = addFun.invoke(10, 20)
默认参数:定义函数变量时可以指定默认值
fun info(name:String = "zhangsan",age:Int){ println("name=$name age=$age")}
具名参数:调用函数时可以指定参数(没有顺序)
info(age=age,name = "李四")
可变参数:
如果接收的参数个数不确定,可以用可变参数表示
fun add(vararg arr: Int): Int {
var result = 0
arr.forEach {
result += it
}
return result}
顶层函数:Kotlin里面函数可以独立于class类存在,这就是顶层函数
嵌套函数:函数里面定义函数
fun main(args: Array<String>) {
var name = "张三"
fun haha(age:Int){
println("名字$name 年纪$age")
return //只能返回当前函数 不会返回main函数
}
haha(20)
println("呵哈")
}
异常处理:
程序抛出异常
fun add(a: Int, b: Int): Int {
if (b == 0) { throw Exception("我是异常")
} else { return a / b }}
Kotlin没有受检异常
处理异常
try { add(10, 0)
} catch (e: Exception) { println("不能为0")
}finally { println("一定执行的代码")}
递归:直接或间接调用自身的一种方法,只需少量的程序就可描述出解题过程所需要的多次重复计算
例如:
递归实现连续数据之和1..100
fun allAdd(n: Int): Int {
if (n == 1) { return 1
} else { return n + allAdd(n - 1) }}
递归实现菲波那切数列1.1.2.3.5.8
tailrec fun fib(n: Int): Int {
if (n == 0) return 0
if (n == 1) return 1
if (n > 1) return fib(n - 2) + fib(n - 1)
return 0}
尾递归:
函数在调用自己之后没有执行其他任何的操作就是尾递归
实现尾递归优化
tailrec fun gsTaAdd(n: Int,result:Int): Int {
if (n == 1) {
return result+1
} else {
return gsTaAdd(n - 1,result+n) }}
运算符重载:
主构和次构函数:
主构:class Person(var name:String,var age:Int){}
次构函数:(次构函数必须要调用主构)
class Person(name:String,age:Int){ constructor(name: String,age: Int,phone:String):this(name, age)}
次构函数间的调用:class Person12(name:String,age:Int){
constructor(name: String,age: Int,phone:String):this(name, age)
constructor(name: String,age: Int,phone: String,email:String):this(name, age, phone)}
init:调用主构函数,调用次构函数,都会执行init
class Person(){//这里如果没有()就代表没有无参构造函数 init { println("执行了init方法") } constructor(name:String):this()}
主构 次构 init调用顺序:无论调用主构还是次构都会执行init
调用次构先执行init再执行次构中的操作
保存主构中的参数:
在init方法中保存:class Person(name:String,age:Int){ var name = "" var age = 0 init { this.name = name this.age = age } }
变量申明时保存:class Person(name:String, age:Int){ var name = name var age = age}
主构函数参数的var和val:
参数没有var和val修饰,参数在其他地方不能使用class Person8(name:String,age:Int){}
参数有var修饰,可以使用,可以修改class Person(var name:String,var age:Int){ override fun toString(): String { return “Person(name=
age)” }} val person = Person8(“张三”,20)person.name = “李四”
参数有val修饰,可以使用,不能修改class Person(val name:String, val age:Int){ override fun toString(): String { return “Person(name=
age)” }}
次构函数参数使用:次构中参数不能加var或者val修饰
次构参数使用 class Person11(var name: String, var age: Int) { var phone: String = “” constructor(name:String,age:Int,phone:String):this(name,age){ this.phone = phone }}
封装:隐藏内部细节实现,只保留对外接口 通过private
class Restaurant{ //点餐 fun order(){ getTicket() } private fun getTicket(){ println(“取到点餐票了”) }}
类的继承:
普通继承open关键字open class Father{ var name:String = “” var age:Int = 0 open fun sayHello(){ println(“父类hello”) }}class Son:Father(){ }
方法继承和属性继承:方法继承和属性继承也都是通过open关键字
open class Father2{ open var name = “小头爸爸” var age = 30 open fun sayHello(){ println(“hello”) }}class Son2: Father2(){ override var name = “大头儿子” override fun sayHello() { super.sayHello() }}
继承父类主构:
子类主构继承父类主构:
open class Human(val name:String,var age:Int)class Man(name:String,age:Int):Human(name,age)
子类次构继承父类主构:
open class Human(var name:String, var age:Int)class Woman: Human { constructor(name:String,age:Int):super(name,age) constructor(name:String,age:Int,phone:String):super(name,age) constructor(name:String,age:Int,phone:String,email:String):this(name,age,phone)}
抽象类:
抽象类是具体类型的抽象,用abstract表示
abstract class IHuman1(val name:String,val age:Int){ abstract fun eat()}
接口:
接口用interface 表示
interface Ride{ fun rideBike()}
抽象类反映事物的本质,接口代表能力
类只能单继承,接口可以多实现
多态:多态就是同种功能不同的表现形式.
定义抽象类和子类
open abstract class Animal{ abstract fun call()}class Dog: Animal() { override fun call() { println(“汪汪汪”) } }class Cat:Animal(){ override fun call() { println(“喵喵喵”) } }调用 val animal1:Animal = Dog()val animal2:Animal = Cat()
智能类型转换:当判断出类型之后就自动将类型转换成该类型了
open class IAnimal class IDog : IAnimal() { fun wangwang() { println(“狗汪汪叫”) }}val animal1: IAnimal = IDog()if (animal1 is IDog) animal1.wangwang()
嵌套类和内部类:
嵌套类:class OutClass{ var outName = “张三” class InClass{ fun sayHello(){ //println(outName) 无法访问外部类中字段 } }}
内部类inner: class OutClass1{ var outName = “张三” inner class InClass{ fun sayHello(){ println(outName) //可以访问外部类中字段 } }}
内部类中使用this:
可以指定内部this和外部this:
class OutClass2 { var name = “张三” inner class InClass { var name = “李四” fun sayHello() { println([email protected]) } }}
泛型:
泛型就是参数化类型class Box(var value: T)//不知道具体传递的类型
中缀表达式:
class A {
infix fun p(str: String): Unit {
println(str)
}
}
A() p "haha"