kotlin基础

1、基本数据类型

类型 字节数
Boolean 1byte
byte 1byte
Char 2byte
Short 2byte
Int 4byte
Float 4byte
Long 8byte
Double 8byte

2、变量

 //可变变量
    var a:Int = 10
    a=20
    //不可变变量
    val b:Int=10

    //普通字符串
    val place = "吉林省长春市"
    //原样输出字符串
    val places = """
        |吉林省
        |长春市
    """.trimMargin()
    println(places)

kotlin基础_第1张图片
kotlin基础_第2张图片
3、函数
kotlin基础_第3张图片

函数式编程 : 函数可独立于对象 单独存在 这样的函数叫做 顶层函数 顶层函数内可以定义函数 叫嵌套函数

字符串模板:

val place1 = "天坛公园"
val str2 =  "今天来到${place1},首先映入眼帘的是$place1 的${place1.length}个大字"

if else 语句

//kotlin 没有三元运算符
    fun max(a:Int,b:Int):Int{
        if(a > b){
            return a
        }else {
            return b
        }
    }
    //if语句精简版 kotlin 的if语句是有返回值的 函数式编程思想 声明式 和 表达式 函数思想 区别
    fun max1(a:Int,b:Int):Int{
       return if(a > b) a else b
    }

for 和 foreach 循环
kotlin基础_第4张图片
运算符的重新定义:

class Girl{
        //operator 用来重新定义运算符
        operator fun plus(girl:Girl):Int{
            return this.age+girl.age
        }
        val name = "小明"
        var age = 20
    }

val girl1 = Girl()
    val girl2 = Girl()
    girl2.age = 30;
    val age = girl1+girl2
    println(age)

多重循环的标签出返回

  //多重循环的标签出返回
    val str4 = "abc"
    val str5 = "efg"

    tag1@for (c1 in str4){
        tag2@for (c2 in str5){
            if(c1 == 'b' && c2 =='f'){
                //此时只用break只会跳出里层循环 外层循环还会执行
                break@tag1
            }
        }
    }

区间定义与遍历:
kotlin基础_第5张图片
kotlin基础_第6张图片
数组定义:
kotlin基础_第7张图片
kotlin基础_第8张图片
kotlin基础_第9张图片
when表达式:

 //when 表达式 分支支持区间 条件语句都可以支持
    fun todo(age:Int):String{
        when(age){
            is Int->{
                return ""
            }
            1,2,3,4,5,6 ->{
                return ""
            }
            in 1..6 -> {
                return ""
            }else->{
            return ""
        }
        }
        return ""
    }
    //不带参数的when语句
    fun todo1(age:Int):String{
        when{
            age is Int->{
                return ""
            }
            age == 6 ->{
                return ""
            }
            age in 1..6 -> {
                return ""
            }else->{
            return ""
        }
        }
        return ""
    }
      //when表达式的返回值 返回值为分支大括号里的最后一行
    fun todo2(age:Int):String{
        return when{
            age is Int->{
                 ""
            }
            age == 6 ->{
                 ""
            }
            age in 1..6 -> {
                 ""
            }else->{
             ""
        }
        }
        return ""
    }

函数表达式: 函数体只有一行时
kotlin基础_第10张图片
获取函数引用:
在这里插入图片描述
kotlin基础_第11张图片
匿名函数:
在这里插入图片描述
默认参数:
在这里插入图片描述
在这里插入图片描述
可变参数:
kotlin基础_第12张图片
在这里插入图片描述
4、异常
异常处理:
编译时异常 :指的是某些函数抛出了异常,在我们调用时必须捕获或抛出去 必须处理
运行时异常 :指的是运行时发生的异常,编译期无法发现
kotlin不检查编译时 异常

5、面向对象
kotlin 会自动加入set 和 get方法

//自动生成get set方法 字段私有
    val person = Person()
    println(person.name)
    //set方法不可见 加上private set

class Person{
        var name:String = "李四"
            //set方法的可见性 加上private set
            //name 的set方法变为私有 外界无法访问
        private set
        var age:Int = 20
    }

//修改或重写set方法
class Person{
        var name:String = "李四"
            //访问器的可见性 加上private set
            //name 的set方法变为私有 外界无法访问
        private set
        var age:Int = 20
            //重写set方法 利用field来代替age修改值 否则会递归调用set方法
        set(value) {
            if(value < 150 ) field = value else field = 150
        }
    }
//构造函数参数在类上直接填充
//init函数 充当了构造方法块
    class Person1(name:String,age:Int){
        var name:String = ""
        var age:Int = 0
        //构造函数里的代码都可以放到init中
        init {
            this.name = name
            this.age = age
        }
    }
//构造函数简化 构造参数加var 或 val 则自动创建填充
//加上var后,自动创建name和age属性,并通过参数赋值
    class Person2(var name:String,var age:Int){

    }
//次构函数 用来重载构造函数 :冒号用来调用主构函数
    class Person2(var name:String,var age:Int){
        var phone:String = ""
        //次构函数调用主构函数
        constructor(name:String,age:Int,phone:String):this(name,age){
            this.phone = phone
        }
        constructor(name:String,age:Int,phone:String,address:String):this(name,age){

        }
    }
    

类继承:

 	var son = Son()
    println(son.name)
    println(son.age)
    son.honbe()
    
	冒号 代表 继承
	class Son:Father(){
        fun tt(){
            println(name)
        }

        override fun honbe() {
            super.honbe()
        }
    }
    //能够被继承 必须加上open关键字
    open class Father(){
        //属性继承
        open var name:String = ""
        open var age:Int = 20
        //方法继承
        open fun honbe(){

        }
    }

接口实现:

//类反应事物的本质 接口反应事物的能力
    var xiaoming = Xiaoming()
    xiaoming.no_id
    xiaoming.drive()
    xiaoming.ride()
    xiaoming.run()

class Xiaoming:Human(),RideBike,driveCar{

        //接口属性实现
        override var no_id: String = ""
        //接口方法实现
        override fun drive() {
            println("小明学会开车")
        }
        //接口方法实现
        override fun ride() {
            println("小明学会骑自行车")
        }
    }
    open class Human{

    }
    interface driveCar{
        //接口里定义属性
        var no_id:String
        //接口里定义方法
        fun drive()
        //接口里也可以实现方法
        fun run(){
            println("接口里定义的方法 直接实现 实现类里可以不实现该方法")
        }
    }
    interface RideBike{
        fun ride()
    }

kotlin 类型强制转换

 class Dog:Anima(){
        fun sound(){
            println("")
        }
    }
    abstract class Anima{

    }
    
     var anima:Anima = Dog()
    //通过 as 关键字 强制转换
    val ani:Dog = anima as Dog
    ani.sound()
    // 通过 is 关键字 判断是否可以强转
    //判断成功后 可不需要 as 强转 即可使用
    if(anima is Dog){
        anima.sound()
    }

嵌套类 和 内部类

//inclass 为静态类  可通过outclass直接点出来创建
    //静态类 与 外部无关 数据无法互通  java是可以互通的
    //inner 关键字可以改变内部类为 非静态
    //
    var inClass = outClass().inclass()
    
	class outClass{
        var name:String=""
        //嵌套类 属于 静态类 无法访问外部非静态属性
        // inner关键字 可以改变内部类为 非静态
        //通过this关键字访问内部或者外部属性
        inner class inclass{
            var name:String = ""
            fun say(){
                println("你好${this.name}")
                println("你好${[email protected]}")
            }
        }
    }

泛型:

	//定义抽象泛型箱子类 此类包含一个有参构造方法
	open abstract class Box<T>(var thing:T)
	//定义箱子类的子类 该子类必须重载该有参构造方法 并且调用父类有参构造方法 且传入参数 同时明确其泛型类型
    class FruitBox(thing:Fruit):Box<Fruit>(thing)
    //定义箱子类的子类 重载并调用了父类构造方法,子类不明确父类泛型类型时 向父类传递子类泛型
    class SomeBox<Q>(thing:Q):Box<Q>(thing)
    //泛型上限 Q只能是Fruit子类
    class MuchBox<Q:Fruit>(thing:Q):Box<Q>(thing)
    //定义抽象水果类
    open abstract class Fruit
    //定义水果类的子类
    class apple:Fruit()
    //定义水果类的子类
    class orange:Fruit()

	//泛型投射 out 关键字允许传入Fruit的子类的list 否则不允许 (java中是允许的)
	//out相当于java中的 (? extends Fruit)
	fun setFruitList(list:ArrayList<out Fruit>){
        println(list.size)
    }
    //in 关键字允许传入Fruit的父类 list
    // in 相当于java中的(? super Fruit)
    fun setFruitList(list:ArrayList<in Fruit>){
        println(list.size)
    }
    //如果没有out关键字 不允许传入apple list 只能传入 Fruit list
	var array = ArrayList<apple>()
    setFruitList(array)
    
    //星号* 投射
    //* 表示 可以传入任意类型的list集合
    // * 相当于java中的 ?
    fun setFruitList(list:ArrayList<*>){
        println(list.size)
    }
    
	//泛型函数
	//泛型函数 先定义泛型  再使用泛型
    fun <T> pabType(thing:T){
        when(thing){
            is Int->{
                println("")
            }
            is String->{
                println("")
            }
            else->{
            println("")
            }
        }
    }
    
    //获取泛型类型
    inline fun <reified T> fan(thing:T){
        //获取泛型类型 加 (java里需要通过反射来获取,因为运行期泛型会擦除)
        println(T::class.java.name)
    }

中缀表达式:
中缀表达式使用条件
1、必须是成员函数或扩展函数(非顶层函数)
2、当前函数必须只有一个参数
3、参数不能是可变参数或默认参数

class person{
		//infix 关键字
        infix fun sayHello(name:String){
            println("hello$name")
        }
    }
	val per = person()
    per.sayHello("xiaoming")
    //中缀表达式
    per sayHello "xiaoming"

	//infix 还可以自定义一些操作符 例如二元组
    //这里的 to 就是infix 自定义的操作符
    val pair2 = Pair<String,Int>("小明",20)
    val pair3 = "小明" to 20

委托模式:
接口委托

   //定义接口能力
    interface WashPower{
        fun wash()
    }
    //实现接口能力
    class BigSon:WashPower{
        override fun wash() {

        }
    }
    //委托接口能力
    class SmallFather:WashPower by BigSon(){

    }
    //委托接口能力 动态委托 将委托人传入构造函数
    class SmallFather1(washPower: WashPower):WashPower by washPower{

    }
    //委托接口能力 能力加强
    class SmallFather2(var washPower: WashPower):WashPower by washPower{
        override fun wash() {
            println("加强委托能力")
            washPower.wash()
        }
    }

属性委托

//将Son1的money 的 get set 方法委托给Mother
    class Son1{
        var money:Int by Mother()
    }
    class Mother{
        operator fun getValue(son1: Son1, property: KProperty<*>): Int {
            return money
        }

        operator fun setValue(son1: Son1, property: KProperty<*>, i: Int) {
            money+=i
        }

        var money:Int = 0
    }

惰性加载和延迟加载:

   class Person3{
        //类创建加载时 name 属性就会加载并初始化
        val name:String = ""
        //优化 使用该属性的时候再加载 惰性加载
        //必须使用val 不可变
        //by lazy 的返回值是 最后一行
        //by lazy 属于线程安全 同步块
        val name1:String by lazy { "张三" }
        //lateinit关键字 延迟加载 没有初始值 必须使用var 以后忘记赋值 运行会抛异常 通过异常准确定位错误
        lateinit var name2:String
        fun setName2(){
            name2 = "张三"
        }
    }

扩展函数:
扩展函数是 不改变类的情况下添加函数
扩展String 类:

//当前String 不可为空
    fun String.myStringIsEmpty():Boolean{
        return this.length == 0
    }
    //当前String 可以为空 当String为null时 返回true
    fun String?.myStringIsEmpty1():Boolean{
    	//this 可访问当前类或当前类属性
        return this==null || this.length == 0
    }

	var name:String? = null
    //name做非空判断 如果为null 返回null
    val flag:Boolean? = name?.myStringIsEmpty()
    //name不做非空判断 因为myStringIsEmpty1可传null 传null时返回true
    val flag1:Boolean = name.myStringIsEmpty1()

子类调用父类扩展函数:

	//定义父类
	open class Father1
	//定义子类
    class Son2:Father1()
    //扩展父类函数
	fun Father1.sayhello(){
        println("")
    }
    //子类调用父类扩展函数
    val son3 = Son2()
    son3.sayhello()

kotlin单例模式:

//object关键字将类utils变为 单例模式
//此单例模式下 类的所有属性为static静态类型
//所以object单例模式 只适用于 属性较少的类 否则会浪费资源
object utils{
        val name:String = ""
        fun sayHello(){
            println("")
        }
    }

//自定义 单例模式
//1、将该类构造函数变为私有 通过 private constructor关键字
//2、通过伴生对象companion object关键字定义静态属性instance
//3、通过懒加载初始化instance 懒加载确保instance只初始化一次 且线程安全
 class Person4 private constructor(){
        var name:String = ""
        //伴生对象companion object块内的属性为静态static
        companion object{
            var age:Int = 20
            val instance:Person4 by lazy { Person4() }
        }
    }
//单例调用
Person4.instance.name

枚举类:

//enum 关键字定义枚举
enum class Color(var r:Int,var g:Int,var b:Int){
        RED(255,0,0),BLUE(0,255,0),GREEN(0,0,255)
    }
//枚举调用
Color.BLUE.r

数据类:
data关键字为该类 实现了
1、构造方法
2、get set方法
3、toString方法
4、equces方法
5、copy方法
6、hashcode方法
7、component方法 (component1返回第一个元素 component2返回第二个元素)

 data class News(var name:String,var title:String,var content:String)
 var news = News("名称","标题","内容")
    news.name
    news.component1()
    news.component2()
    val(namess,title,content) = News("名称","标题","内容")
    println(namess)

密封类:
关键字 sealed 代替 open
父类为密封类 子类可以封装进父类
超强的枚举

//定义密封父类 其中两个子类在密封类内 一个子类在密封类外
sealed class NedStack{
        class Ned1:NedStack(){}
        class Ned2:NedStack(){}
    }
    class Ned3:NedStack(){}

//利用密封类判断子类类型
fun hasRight(nedStack: NedStack):Boolean{
        return when(nedStack){
            is NedStack.Ned1->true
            is NedStack.Ned2->true
            else -> false
        }
    }

集合:
list集合

// listof 生成只读集合  不能添加 不能修改
    val list = listOf("","")
    //mutableListOf生成的集合 为可变集合 可添加 可修改
    val list1 = mutableListOf("","")
    //创建java list集合
    val list2 = arrayListOf("","")
    val list3 = ArrayList<String>()
    //集合过滤
    //找到集合里的某个元素
    val l1 = list.find {it:String ->
        it.startsWith("张")
    }
    //过滤得到包含返回为true的元素的一个新集合
    val l2 = list.filter {it:String ->
        it.startsWith("张")
    }
    //把一个集合过滤出的元素添加到另外一个集合中
    list.filterTo(list1,{it:String ->
        it.startsWith("张")
    })
    //把一个集合中下标为偶数的元素过滤出来
    val l3 = list.filterIndexed { index:Int, s:String ->
        index%2 == 0
    }
    //集合排序
    class Person2(var name:String,var age:Int)
    //list存储基本类型或String 直接排
    list.sorted() //正序
    list.sortedDescending() //倒叙
    //list存储引用类型,按引用类型的字段排
    val list4 = listOf<Person2>(Person2("",10))
    //按照Person2的age字段正序排列
    list4.sortedBy { it:Person2->
        it.age
    }
    //按照Person2的age字段倒叙排列
    list4.sortedByDescending {it:Person2->
        it.age
    }
    //最值
    list.max()
    list.min()
    list4.maxBy {it:Person2->
        it.age
    }
    list4.minBy { it:Person2->
        it.age
    }
    //分组
    //张姓一组 李姓一组 其他一组
    val map:Map<String,List<String>> = list.groupBy {it:String->
        when(it.substring(0,1)){
            "张"->"张"
            "李"->"李"
            else ->"其他"
        }
    }
    //去重复
    list.toSet() //变成set集合 去重复
    //基本类型或String直接去重
    list.distinct()
    //引用类型 去重Person2 名字相同的对象
    list4.distinctBy {it:Person2->
        it.name
    }
    //去重 同姓
    list4.distinctBy {it:Person2->
        it.name.substring(0,1)
    }
    //集合拆分 拆成一个二元组
    val pair4:Pair<List<String>,List<String>> = list.partition { it:String->
        it.startsWith("张")
    }
    //集合map函数 处理集合数据 返回新集合
    //取该集合元素的每一个首字母
    val list5:List<String> = list.map { it:String->
        it.substring(0,1)
    }
    //集合相加
    //把集合元素某个属性相加结果 返回
    val allAge:Int = list4.sumBy { it:Person2->
        it.age
    }

set集合 元素不可重复

// setOf 生成只读集合  不能添加 不能修改
    val set = setOf("","")
    //mutableSetOf生成的集合 为可变集合 可添加 可修改 不可重复
    val set1 = mutableSetOf<String>()
    //创建java set集合 TreeSet 顺序集合
    val set2 = TreeSet<String>()

map 集合

// mapOf 生成只读集合  不能添加 不能修改
    val map1 = mapOf<String,Int>()
    val map2 = mapOf(1 to "",2 to "")
    //mutableMapOf 生成的集合 为可变集合 可添加 可修改
    val map3 = mutableMapOf(1 to "",2 to "")
    //创建java map 集合
    val map4 = HashMap<Int,String>()

函数式编程:
函数式编程就是 函数可以作为方法的返回值,也可以作为方法的参数
函数和类都是一等公民 没有线程安全问题 高并发比较适用 但是不能完全代替面向对象编程
函数是 不保存状态的 执行完即销毁 调用多少次 如下打印出来的都是10

fun test(){
        var a = 10
        println(a)
        a++
    }

闭包可以让函数保存状态
闭包:一个函数返回了一个内部函数,该内部函数引用了外部函数的相关参数和变量,我们把该返回的内部函数成为闭包
kotlin中的闭包就是lambda表达式

fun test1():()->Unit{
        var a = 10
        return {
            println(a)
            a++
        }
    }

高阶函数:就是 某个函数将函数作为参数传递

如下 定义了两个函数add1和sub 以及一个 高阶函数cacl

//将函数作为参数
    //a:第一个参数 b:第二个参数 c:函数(包括参数和返回值)  最后返回Int
    fun cacl(a: Int,b: Int,c:(Int,Int)->Int):Int{
        return c.invoke(a,b)
    }
    fun add1(a:Int,b:Int):Int{
        return a+b
    }
    fun sub(a:Int,b:Int):Int{
        return a-b
    }

高阶函数的调用
函数作为参数时,要使用其引用类型

	val a1 = 10
    val b1 = 20
    var sum = add1(a1,b1)
    var sum1 = sub(a1,b1)
    //传入函数的引用
    var sum2 = cacl(a1,b1,::add1)
    var sum3 = cacl(a1,b1,::sub)

lambda表达式 就是 匿名函数

var sum4 = cacl(a1,b1,{m,n->
        m+n
    })
var sum5 = cacl(a1,b1,{m,n->
        m-n
    })
//lambda表达式如果是最后一个参数,则可以写到括号外
    var sum6 = cacl(a1,b1){m,n->
        m-n
    }
//匿名函数(lambda)的定义及使用
	//使用()调用
	{
        println("")
    }()
    //使用invoke调用
    {
        println("")
    }.invoke()
//带参数及返回值的匿名函数(lambda)
    {
        a:Int,b:Int->
        a+b
    }(10,20)
//接收匿名函数(lambda)的返回值
val result = {
        a:Int,b:Int->
        a+b
    }(10,20)
//匿名函数(lambda)的引用
 val foo:(a:Int,b:Int)->Int ={
        a:Int,b:Int->
        a+b
    }
    foo(10,20)
    foo.invoke(10,20)
 val fo:()->Unit = {
        println("")
    }
    fo()
    fo.invoke()
    //可空的匿名函数(lambda)的引用
 val fooo:((a:Int,b:Int)->Int)? ={
        a:Int,b:Int->
        a+b
    }
//匿名函数(lambda)中 it的使用
    //定义一个高阶函数 第一个参数为Int类型,第二个参数为函数类型(该函数的参数为int类型,返回值为int类型),返回值为int类型
    fun haha(a:Int,b:(c:Int)->Int):Int{
        return b(a)
    }
    //调用这个高阶函数 lambda表达式只有一个参数时 默认用it来表示
    val mm = haha(10){
         it+10
    }
    val mn = haha(10){a->
        a+10
    }
    println("===========================$mm")
    println("===========================$mn")
    //lambda表达式的返回值
    //lambda表达式的返回值是 函数的最后一行 不需要return语句

四大表达式
Apply 大范围的控制处理

//1、apply是所有类型的扩展函数 任意类型都有Apply函数扩展 Apply参数是一个调用者的函数
class Datas{
        var name = ""
        fun da(){
            println("")
        }
    }
    fun set(block:()->Unit){
        block()
    }
    fun set1(block:Datas.()->Unit){
        Datas().block()
        block(Datas())
    }
    set{

    }
    set1 {
        name = ""
        da()
    }
	//2、apply的参数是一个调用者的扩展函数T.()->Unit
    //3、lambda表达式里this代表调用者
    //4、在lambda表达式里可以访问调用者的方法
    //5、apply函数的返回值就是 调用者本身
    list1?.apply {
        add("")
        this.set(0,"")
        val v = this.get(0)
    }?.add("")

Let

	//1、let是所有类型的扩展函数 任意对象都有let扩展函数
    //2、let参数也是一个函数 该函数参数是let的调用者本身
    //3、let函数的返回值 就是他参数函数的返回值 也就是lambda表达式的返回值(lambda表达式的最后一行)
    list1.let {
        it.add("")
        ""
    }.length

With

	//1、with是一个独立的函数 任意地方可以调用
    //2、with函数需要接收两个函数 第一个参数任意类型a 第二个参数是a的扩展函数,该函数返回值就是with函数的返回值
    //3、with函数的返回值 是第二个参数的返回值
    with(list1,{
        this.add("")
        ""
    }).length
    //括号前移
    with(list1){
        this.add("")
        ""
    }.length

Run

	//1、run是所有类型的扩展函数 任意类型都有run扩展函数
    //2、run函数参数是调用者的扩展函数 该函数的返回值 就是run函数的返回值
    //3、run函数的返回值就是其参数的返回值
    list1.run {
        this.add("")
        ""
    }.length

函数回调

	//处理对象
	class Oyi(val name:String){}
	//处理对象工具类
    class boy{
        fun findOyi():Oyi{
            val oyi = Oyi("海天")
            return oyi
        }
    }
    //定义函数回调
    class superMa(){
        fun getOyi(f:(boy)->Unit){
            Thread{
                Thread.sleep(2000)
                val b = boy()
                f(b)
            }.start()
        }
    }
    val superma = superMa()
    //执行函数回调
    superma.getOyi {
        val oyi = it.findOyi()
    }

你可能感兴趣的:(kotlin,kotlin)