Kotlin基础知识总结

kotllin基础

  • 输入输出

    输出

    print 不换行

    println 换行输出

    kotlin里面语句不需要分号

    输入

    • readLine()
      • 返回值是 ?的,表示可能没有想要的数据
      • 使用 !! 表示肯定有
    fun main{
        //从终端接收字符串
    	var a = readLine()!!
        //转为Int
        val temp = readLine!!.toInt
    }
    
    • 使用阅读器Scanner来接收

      //使用阅读器Scanner来接受
      //终端 文件 扫描仪
      //得到一个扫描仪
      val scanner = Scanner(System.`in`)
      //接收数据
      val b = scanner.nextInt()   //整数
      val c = scanner.nextLine()  //字符串
      val d = scanner.nextFloat()  //字符串
      

    类型和变量定义

    常用类型 Int Long Double Float Char Boolean Short

    ​ String Any(任意类型)

    val:不可变的变量

    var:可变的变量

    注:变量的作用域从定义开始到对应代码块结束

    //类型自动推断
        val b = 10
        val c = 10.0
        val d = 10f
        val e = 10L
        val f = 'c'
        val g = "abc"
        val h = true
        
        //明确指定对应的数据类型
        val a1:Int = 10
    	val f1:String = "abc"
    
    	//字符串模板
    	println("this is $a this is $b")
    	println("this is ${a}this is $b")
    

    可选类型

    定义变量时最好初始化,不知道如何初始化时,可以定义为可选类型

    fun main() {
    
        /**
        给一个变量赋初值 不知道具体值时,赋值为null 空
         
         */
    
        //可选类型
        //有值
        //没有值
        val name:String? = null
    
        println("my name is $name length is ${name?.length}")
        // println("my name is $name length is ${name!!.length}")	确定有值才可以强制解包
    
    }
    

    异常处理

    fun main() {
        try {   //尝试执行这段代码
                //一旦代码出现异常 停止执行try里面的代码
            val a = readLine()!!.toInt()	//NumberFormatException
            println("here1")
        }catch (e: Exception){  //如何出现某种类型的异常就捕获
            //得到异常之后怎么处理
            //打印错误信息
            // println(e.message)
            // e.printStackTrace()
        }
    
        println("here2")
    
    }
    

    when语句

    fun main() {
    
        /**
         switch(a){ //支持int char
         case 1:
            break;
         case 2:
            break;
         default:
            break;
         }
    
         1.支持所有类型
         */
    
    
        val a = 10
        when(a){
            0   -> println("0")
            10  -> println("10")
            20  -> println("20")
            else -> {
                println("others")
            }
        }
    
        val name = "jack"
        when(name){
            "jack" -> println("jack")
            "rose" -> println("rose")
            else -> println("i don't know")
        }
    
        //区间
        when(a){
            in 0..10 -> {}
            in 11..20 -> {}
        }
        
        //不在区间中
        when(a){
            !in 0..10 -> {}
            !in 11..20 -> {}
            else -> {}
        }
        
        //判断变量的类型
        val temp:Any? = null
        when(temp){
            is String -> {}
            is Int -> {}
            else -> {}
        }
        
        //kotlin 中无非0即真的说法
        while (true){
            
        }
    }
    

    数组和循环

    数组的创建

    fun main() {
        
        //创建一个拥有预留空间的数组,并且给相应的初始化值
        val  a1: Array<Int> = Array(5,{0})
        val  a2: Array<Int> = Array(5){0}
        val  a3: Array<Int> = Array(5){it}
        a1[0] = 1
        a2[1] = 2
        
        //创建数组时明确知道数组元素的值
        val a4 = arrayOf(1,2,3,4,5)
        val a5:Array<String> = arrayOf("jack","rose")
        val a6:Array<Boolean> = arrayOf(true,false)
        val a7 = arrayOf(a1,a2)	
        
    }
    

    循环遍历

        //遍历
        //直接从数组里面取出每一个值 等待操作
        //不关心索引 只关心具体的值
        for (num in a4){
            print("$num ")
        }
        
        a4.forEach { 
            print("$it ")
        }
        
        a4.forEach { num ->
            print("$num ")
        }
    
        //在一个区间取值
        //闭区间
        for (i in 0..10){
            print("$i")
        }
    
        //改变步调
        for (i in 0..10 step 2){
            println("$i ")
        }
    
        //开区间
        for (i in 0 until 10){
            print("$i ")
        }
    
        //关心索引位置
        for(i in a4.indices){   // 0..a4.size-1
            print("$i - ${a4[i]} ")
        }
        
        //同时获取索引和对应的值
        for ((index,num) in a4.withIndex()){
            print("$index - $num")
        }
        
        a4.forEachIndexed { index, item -> 
            println("$index - $item")
        }
    

    函数定义和调用

    用函数封装代码块,方便调用

    //无参 无返回值的函数
    fun foo1(){
    
    }
    
    //有参 无返回值的函数
    fun foo2(a:Int,b:Int):Unit{
    
    }
    
    //有参 有返回值的函数
    fun foo3(a:Int,b:Int):Int{
        return a + b
    }
    
    /**
        类型自动推断
        1.代码块里面只有一条执行语句
        2.省略函数的返回值用 = 来替代
    
     */
    
     fun foo4(a:Int,b:Int) = a + b
    
    //无参 有返回值的函数
    fun foo5():Unit{
        println("hello foo5")
    }
    fun foo6() = println("hello foo6")
    
    fun foo7():Int{
        println("hello f007")
        return 10
    }
    

    函数的引用

    fun main() {
        val f1Ref:()->Unit = ::f1
        val f2Ref:(Int,String)->Boolean = ::f2
    
        //间接访问f1和f2
        f1Ref()
        f2Ref(2,"jack")
    
        val funArrary = arrayOf(::f1,::f3)
        funArrary[0]()
        //  funArrary[0].invoke() invoke直接调用函数
        
        
    }
    
    fun f1(){
        println("f1")
    }
    
    fun f2(a:Int,b:String):Boolean{
        println("f2")
        return true}
    
    fun f3(){}
    
    fun main() {
        buy(20,::cook)
        
        val names = arrayOf("jack","rose")
        
    
    }
    
    fun buy(money:Int,task:()->Unit){
        println("拿着${money}去买菜")
        println("菜买好了")
        task()
    }
    
    fun cook(){
        println("主人 我去烧饭了")
    }
    
    fun baby(){
        println("主人 我去看小孩了")
    }
    

    函数可变参数

    fun main() {
    
        shouMenu("输入密码")
        //arrayOf("输入密码")
        shouMenu("张三","李四")
        //arrayOf("张三","李四")
    
    }
    
    //可变参数 在普通参数前加上个 vararg
    //  此处的menus其实也是字符数组 在传参数时不用加arraryof,更加方便
    fun shouMenu(vararg menus:String) {
        menus.forEach {
            println(it)
        }
    }
    

    函数的引用和高阶引用

    package com.example.myapplication
    
    fun main() {
        //1.用中间变量传递函数的引用
        val center:()->Unit = ::show
        doSomething(10,center)
    
        //2.直接引用函数
        doSomething(20,::show)
    
        val a = 10
    
        //3.直接把函数的实现传进来
        //最后一个参数是函数,可以把函数移到()的外面
        doSomething(30) { println("show") }
    
    }
    
    //对于函数来说,包就是它的作用域
    fun show(){
        println("shou")
    }
    
    fun doSomething(money:Int,task:()->Unit){
        println("get money $money")
        task()
    }
    

    自己用高阶函数实现forEach

    fun main() {
    
        val nums = arrayOf(1,2,3,4,5)
        val names = arrayOf("jack","rose")
    
    //    nums.forEach {
    //        println(it)
    //    }
    
        //自己实现forEach
        nums.myForEach {index,value->
            
        }
        
    }
    
    //高阶函数:函数的参数类型是函数
    fun Array<Int>.myForEach(task:(Int,Int)->Unit){
        for((index,value) in this.withIndex())
            task(index,value)
    }
    
    • 使用高阶函数的一大好处是:可以实现数据回调
    fun main() {
    
        loadData("www.baidu.com",){ data:String?,code:Int?->
            if(data != null){
                println("获取数据成功")
            }
    
            if(code != null){
                println("获取数据失败")
                if (code == -1){
                    println("网址错误")
                }
            }
        }
    
    }
    
        //高阶函数可以实现数据回调
        //-1 网址不对   -2网络不行 -3资源不存在
        fun loadData(url:String,task:(String?,Int?)->Unit){
             if (url.length < 2){
                 //模拟网址有问题
                 task(null,-1)
                 return
             }
    
            println("正在获取数据")
            task("隔壁老王的靓照",null)
        }
    
    
    //高阶函数:函数的参数类型是函数
    fun Array<Int>.myForEach(task:(Int,Int)->Unit){
        for((index,value) in this.withIndex())
            task(index,value)
    }
    

    类简介

    /**
    kotlin 一切皆对象
    类:对一类事物高度抽象,不实际存在 == 属性和方法的封装
    对象:某个类的实例化 实际存在
    
     吃早餐
     面向过程:起床 拿起面包 吃 喝牛奶
     面向对象:
        吃早餐
        对象:张三 全麦面包 AD钙
        类:Person Bread Milk
        属性:Person:name age address
            Bread:brand type
            Milk:brand type
     */
    

    类的定义和实例化

    类的定义

    关键字:class

    Person:类名 首字母大写

    对象的创建/类的实例化

    val v = Person()

    1.用编辑器编写一个类 文件

    2.当程序运行起来,并且需要访问这个类的时候,才会将这个类加载到内存中

    3.受用Person()实例化一个对象

    4.在堆中申请一片内存空间,用于存储这个对象

    5.不需要的时候,释放内存空间

    注意:声明属性时必须初始化或抽象,如果不确定初始值,可用可选类型

    ​ 当声明一个属性为var时系统完成了3件事情

    ​ 1.提供了对应的set方法

    ​ 2.提供了get方法

    ​ 3.提供了一个变量用于存数据(backing-filed)

    ​ 当声明一个属性为val时系统完成了2件事情

    ​ 1.提供了get方法

    ​ 2.提供了一个变量用于存数据(backing-filed)

    class Person{
        //属性必须初始化或抽象
        var name:String = ""
        var name2:String? = null
        var age:Int = 1
    
    
    }
    
    fun main() {
        //注意选需要的包中的类
        //创建一个对象 类的实例化
        val zs = Person()
        val ls = Person()
        //注意张三和李四是不同的
    
        zs.name = "zhangsan"
        zs.age = 20
    
        println("${zs.name} ${zs.age}")
    
    }
    

    属性定义和使用

    注意:

    == 比较对象的值是否相同

    === 比较对象是否相同

    字符串常量在内存的常量区分配内存空间

    class Person{
        //属性必须初始化或抽象
        var name:String = ""
        var name2:String? = null
        var age:Int = 1
    
    
    }
    
    fun main() {
        //注意选需要的包中的类
        //创建一个对象 类的实例化
        val zs = Person()
        val ls = Person()
        //注意张三和李四是不同的
    
        zs.name = "zhangsan"
        ls.name = "zhangsan"
        zs.age = 20
    
        println("${zs.name} ${zs.age}")
    
        val ww = zs
    
        val s1 = String(charArrayOf('j','a','c','k'))
        val s2 = String(charArrayOf('j','a','c','k'))
    
        // == 比值
        if (s1 == s2){
            println("the same")
        }else{
            println("not the same")
        }
    
        // === 比较对象
        if (s1 === s2){
            println("the same")
        }else{
            println("not the same")
        }
    
        if (zs.name == ls.name){
            println("the same")
        }else{
            println("not the same")
        }
    
        if (zs.name === ls.name){
            println("the same")
        }else{
            println("not the same")
        }
    
        if (zs == ww){
            println("the same")
        }else{
            println("not the same")
        }
    
    }
    
    实战:生成一副牌

    扑克牌

    A 2 3 4 5 6 7 8 9 10 J P K

    每一种牌有四种花色

    A♥ A♠ A♣ A♦

    //当需要将多个属性结合为一个整体的时候就需要用到类
    
    class Poker{
        var number:String = ""
        var color:String = ""
    }
    
    fun main() {
    
        val dotArrary = arrayOf("A","2","3","4","5","6","7","8","9","10","J","Q","k")
        val colorArrary = arrayOf("♥","♠","♣","♦")
    
        //可变数组 数组中元素数量可变
        val pokerArray = arrayListOf<Poker>()
    
        dotArrary.forEach { num->
            colorArrary.forEach { color->
                val poke = Poker()
                poke.number = num
                poke.color = color
                pokerArray.add(poke)
            }
        }
    
        pokerArray.forEachIndexed { index, poker ->
            print("${poker.number}${poker.color} ")
            if ((index+1) % 4 == 0){
                println()
            }
        }
    }
    

    注意:不能直接调用类中的属性和方法,先要进行类的实例化,即创建 一个对象

    补充:

    class Car(val brand:String,val color:String){
        val price:Int? = null
        lateinit var engine:String //延迟初始化 但使用前必须要初始化
        val speed by lazy { //延迟加载
            //
            300
        }
    
        //构建对象的时候,init方法就会被调用
        init {
            println("init 方法被调用了 $brand")
        }
    
        fun start(){
            engine = "v8"
            print("brand:$brand engine: $engine speed:$speed")
        }
    }
    
    /**
     * 主构造 Constructor()
     * 当构建参数时,需要外部传递对应的初始数据
     * 次构造
     *      class Car(brand:String, val color:String)
     *      brand:为临时变量,用来接收外部传递的数据,类内部的方法无法访问这个变量
     *              1.将这个变量的值的属性来接收 val tt = brand
     *              2.在init方法中可以使用 init{}
     *
     * 属性:存数据
     * 方法/函数:
     */
    
    fun main() {
        val bz = Car("奔驰","宝马")  //调用构造函数  
        bz.start()
    }
    
    /**
     * 主构造 Constructor()
     * 当构建参数时,需要外部传递对应的初始数据
     * 次构造
     *      class Car(brand:String, val color:String)
     *      brand:为临时变量,用来接收外部传递的数据,类内部的方法无法访问这个变量
     *              1.将这个变量的值的属性来接收 val tt = brand
     *              2.在init方法中可以使用 init{}
     *
     * 属性:存数据
     * 方法/函数:
     */
    
    fun main() {
        
    //    直接引用
    //
    //
    //    间接调用
    //    在定义变量时使用函数的引用来初始化
    //    val result:(msg:String)->Int = ::success
    //    val code = result("成功")
    //    println("get the code $code")
    //
    //    在定义变量时直接初始化
    //    { 这个函数的参数 -> //当只有一个参数时 可以省略 默认是it
    //     具体实现
    //     如果有返回值 不要写return 最后一行就是返回值
    //    }
        val result:(String)->Int = {
            println(it)
            200
        }
        result("jack")
    	
        //传入函数的引用
        //load(::success,::failure)   //耦合 低耦合高内聚
    
        //传入具体的实现
        load({
            println("success: $it")
            0
        }) {
            println("success: $it")
        }
    
    }
    
    fun success(msg:String):Int{
        println(msg)
        return 200
    }
    
    fun failure(msg:String):Int{
        println(msg)
        return 200
    }
    
    
    fun load(right:(String)->Int, wrong: (String) -> Unit){
        //....
        val code = 200
        if (code == 200){
            right("成功的数据")
        }else{
            wrong("错误的数据")
        }
    }
    

    数组和对象的关系

    package com.example.kotlinbasics.day4_class
    
    //    val names = arrayListOf<String>("jack","rose")
    //    val name = names[0]
    //    names.remove(name)
    //    println(("my name is $name"))
    
    
    /**
    class Person{
        val age:Int
    
    //    重写get方法
    //        get() = 20 //明确知道返回值是什么
        get() {
        println("开始查询数据")
        println("查询到数据了")
        return 20
    }
    
    
    //lateinit只能修饰var 不能修饰val
       lateinit var name:String
    
    
    懒加载
    1.节省内存空间
    2.只执行一次 -> 创建单例对象
    3.只有val类型变量能使用懒加载
    
    class Person{
    
       val name:String by lazy{
           "jack"
       }
    
    }
    
     构造函数
        当对象被创建时需要调用的函数 Person()
        当创建时不需要任何函数,那么(默认/主)构建函数可以省略
     什么情况下需要写构建函数 不能省略
        1.创建对象时需要提供默认的属性
        2.有关键字修饰构建函数
    
    次构造函数
    1.可以有多个次构造函数
    2.此构造函数必须调用主构造函数(有主构造函数)
    3.声明在类的内部,使用construtor构建一个函数
    
    构建对象的顺序
        子类 -> 父类1 -> 父类2 -> ... ->Any
                                    创建原始对象
    完整对象 <- 赋值(修饰)<- 赋值(修饰)<- 赋值(修饰)<-
    
     Any:所有类的父类
    
     Person() -> Person 构造函数 -> 父类构造函数 -> Any
    
    
    
     */
    class Person1 constructor(var name:String, var age:Int){
    
        var address = ""
        constructor(address:String,name:String,age: Int) : this(name,age){
    
        }
    
        var score = 0f
    
        fun show(){
            println("$name $age")
        }
    }
    
    fun main() {
    
    }
    

    属性getter和setter方法

    重写get方法

    class Person{
        val age:Int
            //重写get方法
            //get() = 20    //明确知道返回值是什么
            get() {
                //
                println("开始查询数据库")
                println("查询到数据了")
                return  20
            }
    
    }
    
    fun main(){
        val p = Person()
        println(p.age)
    }
    

    重写set方法

    class Person{
        var height:Float = 0f
        var age:Int = 0
            //重写get和set后 可以做一些额外的事情
        	//实际上是由field存值
            set(value) {
                if (value == 1){
                    height = 50f
                }
                field = value
            }
    }
    
    fun main(){
        val p = Person()
        p.age = 1
    }
    

    lateinit延迟加载

    class Person{
        //若到某个时刻才能给一个值 可用延迟加载
        //lateinit只能修饰var 不可修饰val
        lateinit var name:String
    
    }
    
    fun main() {
        val p = Person()
        p.name = "jack"
        val l = p.name.length
    
    }
    

    by lazy 懒加载

    class Person{
        /**
         懒加载
         1.节省内存空间
         2.只执行一次 -> 创建单例对象
         3.只有val类型变量能使用懒加载
         */
        val name:String by lazy {
            println("hello")
            "jack"
        }
    }
    
    fun main() {
        val p = Person()
        println(p.name)
        println(p.name)
        println(p.name)
    
    }
    

    主构造函数

    /**
        构造函数
            当函数被调用的时候需要调用的函数    Person()
            当创建对象时不需要任何参数,那么(默认/主)构造函数可省略
    
        什么时候需要写构造函数
        1.创建对象时需要提供默认的属性
        2.有关键字修饰构造函数
    
    
     */
    class Person constructor(var name:String, var age:Int){
            //val t = "jack"
            var score = 0f
    
            fun show(){
                println("$name $age")
            }
    
        }
    
    fun main() {
        val p = Person("jack",20 )
        p.name = "jack"
        p.age = 0
        p.score = 99f
    
    }
    

构造函数

  • 主构造函数

    ​ 关键字:Constructor(可省)

    ​ 用法:当需要外部传入对应的初始值

    ​ eg:class Car(brand:String, val color:String)

    ​ brand:为临时变量,用来接收外部的数据,类内部的方法无法访问这个变量

    ​ 1.将这个变量用属性来接收 val tt = brand

    ​ 2.在init方法中可以使用(init方法在创建对象时就会被调用)

    ​ color:属性:随时随地都可以访问

    注意:语调val或var时,只是临时变量,不是属性

/**
 * 主构造 Constructor 当创建对象时,需要外部传递对应的初始数据
 * 次构造
 *      class Car(brand:String, val color:String)
 *      brand:为临时变量,用来接收外部的数据,类内部的方法无法访问这个变量
 *              1.将这个变量用属性来接收 val tt = brand
 *              2.在init方法中可以使用 init{}
 *      color:属性 随时随地都可以访问
 *
 */

//去掉val或var时 只是临时变量,不是属性
class Car(brand:String,val color:String){
    val tt = brand
    fun start(){
        print("brand: $tt color: $color")
    }
    
    //创建用户时就会调用init方法
    init {
        println("init 方法被调用了 $brand")
    }
}
fun main() {
    val bz = Car("奔驰","黑色")
    
}

高阶函数实现数据回调

package com.example.kotlinbasics.day4_class

fun main() {
    //直接调用
    //success("")

    //间接调用
    //在定义变量时使用函数的引用来初始化
    //val result:(String)->Int = ::success
    //val code = result("成功")
    //println("get the code: $code")

    //在定义变量时直接初始化
    //{ 这个函数的参数 -> 当只有一个参数时 可以省略 默认是it
    // 具体实现
    // 如果有返回值,最后一行就是返回值,不要写return
    //}
    val result:(String)->Int = { msg ->
        println(msg)
        200
    }

    //load(::success,::failure)   //耦合 低耦合高内聚

    load({
        println("success: $it")
        0
    },{ println("failure: $it")
    0
    })





}

fun downloadSuccess(){

}

fun success(msg:String):Int{
    println(msg)
    return 200
}

fun failure(msg: String):Int{
    println(msg)
    return 200
}

fun load(right:(String)->Int,wrong:(String)->Int){
    //...
    val code = 200
    if(code == 200){
        right("成功的数据")
    }else{
        wrong("地址不正确")
    }

}

高阶函数作为属性使用

可将高阶函数当作属性使用,扩大作用域

全局变量与局部变量同名,优先调用局部变量 可添加 this. 调用全局变量

//不为null才会调用
callback?.let { 
    it()
}

扩展

作用:在原有的基础上添加新的属性或者函数

​ 1.直接在类里面添加方法或属性(有源代码)

​ 2.如果时封装好的类/系统默认提供的类(没法更改) -> 可以使用拓展方法或属性

语法:fun 类名.方法名(){

}

var Person.age:Int
set(value) {
println(value)
}
get(){
return 20
}

注意:拓展属性不能存值 没有提供field属性

​ set和get方法: set:有了这个值,你要干什么

​ get:怎么给我这个值

package com.example.kotlinbasics.day5_ext

/**
 * 扩展Extension:在原有的基础上添加新的属性或者函数
 * 1.直接在类里面添加方法或属性(有源代码)
 * 2.如果是封装好的类/系统默认提供的类 (没法更改)
 */

class Person{
    val name = "jack"
    fun test(){
        println("test")
    }
}

//扩展属性不能存值 没有提供field属性
var Person.age:Int
    set(value) {
        //有了这个值 你需要干什么
        println(value)
    }
    get(){
        //怎么给我这个值
        return 20
    }

//给Person类添加了一个新的方法 eat
fun Person.eat(){
    println("eating...")
    test()
}

fun Any.show(){
    println(this)
}

fun main() {
    val zs = Person()
    zs.eat()

    val address = "西大"

    address.show()
    2.show()
    zs.show()
    2.4f.show()
	
    //let其实就是一个扩展函数
    3.let{}
    "jack".let {  }

	/**
     * T.let() 给T类型添加的扩展函数 let
     * block:(T) -> R 接收一个参数,参数类型是函数
     */
//    public inline fun <T, R> T.let(block: (T) -> R): R {
//        contract {
//            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
//        }
//        return block(this)
//    }


    }

继承

package com.example.kotlinbasics.day5_ext

/**
 封装 继承 多态
 java kotlin: 单继承
 默认所有的类都是final 需要使用open才能被继承
 子类如果需要重写(重新实现)父类的方法
    需要使用override修饰子类重写的方法
    父类的方法必须使用open修饰 才能被子类重写

 如何封装
    public 公有的(默认) 都可以使用
    private 私有的 当前这个类可用 子类外部类都无法访问
    protected 受保护的 子类可以继承 外部无法访问

 */

open class Father{
    var money = 0
    private var knowLedge = "博士"
    open fun work(){
        println("father work $money $knowLedge")
    }
}

// :表示继承一个类
class Child:Father(){
    //子类重写父类的方法
    override fun work(){
        println("child work $money")
    }
}


fun main() {
    val my = Father()
    val zs = Child()
    zs.money
    zs.work()
}

多态

package com.example.kotlinbasics.day5_ext

open class User(var name:String){
    open fun work(){
        println("$name is working")
    }
}

class Teacher(name: String) :User(name){
    override fun work(){
        //super指的是父类    super.work()
        println("开始上课")
    }
}
class Student(name: String) :User(name){
    override fun work(){
        println("开始学习")
    }
}

//使用父类接收子类 但在调用时会调用对象本身的方法 
fun goToSchool(user:User){
    user.work()
}

fun main() {
    val zs = Student("张三")
    val cc = Teacher("苍苍")
     
    goToSchool(cc)
    goToSchool(zs)

}

1.如何从0到1写项目

  • 找对象
  • 抽类
  • 梳理类与类的关系
  • 类图
  • 梳理类与类的关系
  • 类图
  • 写功能的时序图
  • 写代码
  • 迭代

2.阅读别人的代码

  • 首先找到入口点
  • 理清程序的执行顺序
  • 类图 -> 把控全局
  • 梳理复杂功能的时序图

使用文件保存数据

  • 数据持久化

    • 1.将数据保存到服务器

    • 2.本地的数据库 Room

    • 3.本地(硬盘)

      • 文本 txt -> 字符流 -> 字符输入流/字符输出流(字符IO流)

      • 二进制 image mp3 mp4 -> 字节流 -> 字节输入流/字节输出流 (字节IO流)

        :无法一次性完成读写 多次少量读写

        • 内存 -> 外部(打印机 硬盘 网络) 输出流

        • 外部 -> 内存 输入流

        输入输出以内存为对照物

        • 字符流:Writer/Reader
        • 字节流:OutputStream / InputStream

普通读写文件(一个一个来)

  • 创建文件

    File类管理文件对象

    val file =  File("D:","1.txt")
    
  • 打开文件

  • 写入文件

    //写入数据
    file.writeText("hello Android")       //writeText会覆盖原有文件内容
    file.appendText("I love Android")   //在原有内容上追加
    
  • 读取数据

    val result = file.readText()
    println(result)
    
  • 关闭文件

缓冲输入输出

  • 创建文件

    val file =  File("D:","1.txt")
    
  • 写入数据

    • 创建BufferwdWriter对象
        val bw = BufferedWriter(FileWriter("D:\\1.txt"))      //可以简化为这种形式,推荐
    	
    	//分步
    	//创建Writer对象
    	val fileWriter = FileWriter(file)
        //创建BufferedWriter需要Writer对象,此处是操作File,所以创建了一个FileWriter对象
        val bufferedWriter = BufferedWriter(fileWriter)
    	
    
    • 写入数据
     bw.write("hello jack")
     bw.close() 	//操作完毕后要关闭BufferedWriter对象,节约资源
    
  • 读取数据

    • 创建BufferReader对象

      val br = BufferedReader(FileReader("D:\\1.txt"))
      
    • 读取数据

      val str = br.readText()
          br.close()      //操作完毕后要关闭BufferReader对象
          println(str)
      
package com.example.kotlinbasics.day8_file

import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.io.Writer

/**
 * 数据持久化
 *  1.将数据保存到服务器
 *  2.本地的数据库 Room
 *  3.文件(硬盘)
 *      文本 txt -> 字符流 -> 字符输入流/字符输出流(字符IO流)
 *      二进制 image mp3 mp4 -> 字节流 -> 字节输入流/字节输出流(字节IO流)
 *
 *      流:无法一次性操作 多次少量读写
 *      字符流:Writer/Reader
 *      字节流:OutputStream/InputStream
 *
 *      内存 -> 外部(打印机 硬盘 网络) 输出流
 *      外部 -> 内存(变量)           输入流
 *
 *
 *      创建文件
 *      打开数据
 *      写入数据
 *      读取数据
 *      关闭文件
 *
 *      File类管理文件操作
 *
 *      缓冲输入输出流
 *      BufferedWriter/BufferedReader
 *
 *
 *
 *
 */

fun main() {
    //objectSaveFileOpt()
    //objectReadFileOpt1()
    //objectsSave()
    objectsRead()
}
//文件基本操作
fun fileOpt1(){
    //创建一个文件对象来存取数据
    //val file = File("D:\\Users\\wuliner\\Desktop","1.txt")

    //写入数据
    //file.appendText("I love Android")

    //读取数据
    //val result = file.readText()
    //println(result)
}
//缓冲输入输出操作
fun bufferFileOpt1(){
    //    val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
//    val fileWriter = FileWriter(file)
//    val bufferedWriter = BufferedWriter(fileWriter)
//
//    val bw = BufferedWriter(FileWriter("D:\\Users\\wuliner\\Desktop\\1.txt"))
//    bw.write("Hello Jack")
//    bw.close()

    val br = BufferedReader(FileReader("D:\\Users\\wuliner\\Desktop\\1.txt"))
    val str = br.readText()
    br.close()
    println(str)
}

class Car(val brand:String,val color:String)

//将一个对象写入文件
/**
 * Gson开源库
 *  字符串 -> 对象 fromJson
 *  对象  -> 字符串 toJson
 */
fun objectSaveFileOpt(){
    val car = Car("奔驰","黑色")
    //创建FGeson对象
    val gson = Gson()
    //将对象转化为Json格式的字符串
    val jsonString = gson.toJson(car)
    //创建文件对象
    val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
    //将字符串写入文件中
    file.writeText(jsonString)
    
}

fun objectReadFileOpt1(){
    //创建文件对象
    val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
    //读取数据
    val string = file.readText()
    //创建Gson对象
    val gson = Gson()
    //将Json格式的字符串转化为对象
    val car = gson.fromJson(string,Car::class.java)
    println("${car.brand} ${car.color}")
}

fun objectsSave(){
    val cars = listOf(
        Car("奔驰","黑色"),
        Car("宝马","白色"),
        Car("保时捷","棕色")
    )

    //创建gson对象
    val gson = Gson()
    //将list集合转换为字符串
    val jsonString = gson.toJson(cars)
    //创建文件对象
    val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
    //写入数据
    file.writeText(jsonString)
}

fun objectsRead(){
    //创建文件对象
    val file = File("D:\\Users\\wuliner\\Desktop","1.txt")
    //读取字符串
    val jsonString = file.readText()
    //创建gson对象
    val gson = Gson()
    //将json字符串转化为集合对象
    val objectToken = object : TypeToken<List<Car>>(){}
    val cars = gson.fromJson<List<Car>>(jsonString,objectToken.type)
    cars.forEach{
        println("${it.brand} ${it.color}")
    }
}

collection

package com.example.kotlinbasics.day10_collection

/**
 * 联系人列表
 * 陈珊珊 -> chenshanshan
 * 陈小红 -> CXH
 * A
 * B
 * C
 *      陈珊珊 CSS
 *      陈小红 CXH
 *
 * D
 *
 *  数据的存储结构
 *      小组的存储形式:映射关系 C -> 一组好友
 *                               数组(好友:name  title alphaString )
 *  通讯录:数组(每组数据)
 *  Collection: 接口
 *          size isEmpty contains iterator toArray
 *          add remove containsAll addAll removeAll
 *          clear equals
 *      List: 接口
 *          replaceAll sort
 *          get set
 *          indexOf lastIndexOf
 *          subList
 *    ArrayList: 普通类 实现类
 *          如何创建 - 构造方法(Java 方法名和类名相同,Constructor)
 *              ArrayList(size)
 *              ArrayList()
 *              ArrayList(Collection)
 *
 *      Kotlin: List
 *      是Kotlin的封装
 *      不可变 没有add remove replace
 *      ListOf()
 *      emptyList()
 *
 *      Kotlin:MutableList -> List
 *         可以增删改 add remove clear
 *         mutableListOf()
 *
 *      Kotlin:ArrayList -> MutableList
 *          arrayList()
 *
 *
 */

fun main() {
    // ArrayList -> AbstractList -> AbstractCollection -> Collection -> Iterable
    //           -> List -> Collection -> Iterable

    val nums = arrayListOf(1,2,3,4,5,6,7,8,9,10)
    val temps = arrayListOf<Int>()

    for (num in nums){
        if (num > 5){
            temps.add(num)
        }
    }



    val results = nums.filter { it % 2 == 0 }
    nums.sortDescending()

    val doubleNums = nums.map {
        if(it % 2 == 0){
            it*10
        }else{
            it
        }
    }

    println(doubleNums)


    //println(results)





//    fun <T>ArrayList<T>.myFilter(predicate:(T)->Boolean):List<T>{
//        this.forEach{
//            val tempList = arrayListOf<T>()
//            val result = predicate(it)
//            if (result){
//                tempList.add(it)
//            }
//        }
//
//    }





fun<T,R> Iterable<T>.myMap(call:(T) -> R):List<R>{
    val container = arrayListOf<R>()
    this.forEach{
        val result = call(it)
        container.add(result)
    }
    return container
}



}

高阶函数

  • 常用kotlin扩展函数:let also apply with use

let与also区别

相同点:参数是普通的函数

  • also返回值还是原来的对象

  • let返回值是处理后的结果

apply和with区别

相同点:参数是都是对应类型的扩展函数 ,可以直接在类的内部进行操作

  • apply返回值还是对象本身

  • with返回值是处理后的结果

    use:使用use对文件进行操作 内部有try和catch处理异常 操作完成后会自动关闭文件

package com.example.kotlinbasics.day10_collection

import java.io.BufferedWriter
import java.io.FileWriter


class School{
    var name:String = ""
    var address:String = ""
    var level:Int = 211
    fun show():Int{
        return 0
    }
    fun test(){}
}

//.also apply use let run with
fun main(){
    val xd = School()
    xd.name = "xida"
    println(xd.name)

    //使用also可以使代码更简洁
    val xd1 = School().also {//also的返回值是对象本身
        it.name = "xida"
        println(it.name)
    }

    //没名字的对象称为匿名对象
    //调用后立刻执行also中代码 做了一些事还同时想做其他事
    School().show().also {}

    // apply 可以直接在对象内部进行操作 也可调用外部 可以创建对象后立刻对属性赋值或调用方法
    val xs = School().apply {//apply的返回值是对象本身
        name = "jack"
        address = "荣昌"
        show()
        test()
    }

    School().myApply {

    }

    //use package com.example.kotlinbasics.day10_collection

import java.io.BufferedWriter
import java.io.FileWriter


class School{
    var name:String = ""
    var address:String = ""
    var level:Int = 211
    fun show():Int{
        return 0
    }
    fun test(){}
}

//.also apply use let run with
fun main(){
    val xd = School()
    xd.name = "xida"
    println(xd.name)

    //使用also可以使代码更简洁
    val xd1 = School().also {//also的返回值是对象本身
        it.name = "xida"
        println(it.name)
    }

    //没名字的对象称为匿名对象
    //调用后立刻执行also中代码 做了一些事还同时想做其他事
    School().show().also {}

    // apply 可以直接在对象内部进行操作 也可调用外部 可以创建对象后立刻对属性赋值或调用方法
    val xs = School().apply {//apply的返回值是对象本身
        name = "jack"
        address = "荣昌"
        show()
        test()
    }

    School().myApply {

    }

    //use 使用use对文件进行操作 内部有try和catch处理异常  操作完成后会自动关闭文件
    val bw = BufferedWriter(FileWriter("")).use {

    }

    //let
    //let返回值 是let代码块的返回值
    val temp = School().let {
        20
    }

    //with with的返回值是代码块的返回值
    with(School()) {

    }

}
//自己实现also
//注意传入的是普通函数
fun<T> T.myAlso(call:(T)->Unit):T{
    call(this)
    return this //also的返回值就是对象本身
}

//自己实现apply
//注意传入的参数是对象的扩展函数 就能进入对象的内部
fun<T> T.myApply(call:T.() -> Unit):T{
    this.call()
    return this //apply的返回值就是对象本身
}
    val bw = BufferedWriter(FileWriter("")).use {

    }

    //let
    //let返回值 是let代码块的返回值
    val temp = School().let {
        20
    }

    //with with的返回值是代码块的返回值
    with(School()) {

    }

}
//自己实现also
//注意传入的是普通函数
fun<T> T.myAlso(call:(T)->Unit):T{
    call(this)
    return this //also的返回值就是对象本身
}

//自己实现apply
//注意传入的参数是对象的扩展函数 就能进入对象的内部
fun<T> T.myApply(call:T.() -> Unit):T{
    this.call()
    return this //apply的返回值就是对象本身
}

map映射关系

package com.example.kotlinbasics.day10_collection

import java.util.LinkedList

/*
Set与List区别?
    Set 集合 无序 唯一 不可重复
    List    有序 可以重复
 */


fun main() {
    /**
     * Map
     * 普通好友 -> 普通好友列表
     * String -> List<Friend>
     *  key键  -> value值
     *  唯一       不唯一
     */

    //ArrayList MutableList List
    //HashMap与MutableMap的区别: HashMap用哈希表存值
    //HashMap -> MutableMap -> Map
    //大量删减数据时候适合使用链表 不适合大量查询
    //大量查询 -> ArrayList
    //大量增加和删除 -> linkedList
//    LinkedList
//    LinkedHashMap


    val studentMap:HashMap<String,String> = hashMapOf(
        Pair("班长","老王"),
        Pair("好孩子","老王")
    )

    //得到所有的键  studentMap.keys
    studentMap.keys.forEach{key->
        studentMap[key].also {
            println("$key - $it")
        }
    }
    //得到所有的值 studentMap.values
    studentMap.values
    //得到所有的键值对 studentMap.entries
    studentMap.entries.forEach{
        println("${it.key}-${it.value}")
    }
    val studentMap2:Map<String,String> = hashMapOf()

}

密封类

package com.example.kotlinbasics.day12_class


/**
 * 数据类
 * 密封类 Sealed Class
 *   外部无法继承 同一个包内可以继承
 */


sealed class NetworkResult {
    class Success(val data: String) : NetworkResult()
    class Failure(val errorMsg: String) : NetworkResult()
}

fun main() {
    val result: NetworkResult = loadData()
    when (result) {
        is NetworkResult.Success -> {
            //val ss = result as NetworkResult.Success
            println(result.data)
        }

        is NetworkResult.Failure -> {
            println(result.errorMsg)
        }
    }
}

fun loadData(): NetworkResult {
    //......
    //return NetworkResult.Success("结果")
    return NetworkResult.Failure("地址不正确")

}

sealed class Animal(val name: String, val voice: String)

class Cat(name: String, voice: String) : Animal(name, voice) {
    fun cry() {
        println("$name $voice")
    }
}

class Dog(name: String, voice: String) : Animal(name, voice) {
    fun cry() {
        println("$name $voice")
    }

}

sealed class A
object B : A()
object C : A()

抽象类

package com.example.kotlinbasics.day12_class

/**
 * 抽象类
 *      类:拥有类的功能
 *      抽象:不能创建对象(统筹规划:某些情况下不做具体的事情,子类来做)
 * 为什么要抽象类
 *      制定功能模板 -> 子类按照这个模板去做事儿
 *
 */

abstract class LoginView{
    abstract fun getUserInfo():String
    abstract fun checkInfo(str: String):Boolean
    abstract fun login(info:String):Boolean
    abstract fun startMainView()
    abstract fun loginFailure(err:String)
    //启动页面
    fun startView(){
        //获取用户信息
        val phoneNumber = getUserInfo()
        //验证用户是否正确
        if (checkInfo(phoneNumber)){
            println("验证成功")
        }else{
            println("信息格式不正确")
        }
        //服务器段实现登录校验
        if (login(phoneNumber)){
            //启动主页面
            startMainView()
        }else{
            //登录失败
            loginFailure("用户不存在 ")
        }


     }
 }
class MeituanLoginView: LoginView() {


    override fun getUserInfo(): String {
        return "18098908987"
    }

    override fun checkInfo(str: String): Boolean {
        return str.length == 11
    }

    override fun login(info: String): Boolean {
        println("登录美团服务器...")
        return true
    }

    override fun startMainView() {
        println("启动美团主页面")
    }

    override fun loginFailure(err: String) {
        println("重新进入登录页面")
    }
}

abstract class Person(){
    abstract val name:String

    abstract fun eat()
    abstract fun dress()
    abstract fun action()

    fun live(){
        eat()
        dress()
        action()
    }

}

class Xiaowang :Person(){
    override var name:String
        get() = "jack"
        set(value) {}


    override fun eat() {
        TODO("Not yet implemented")
    }

    override fun dress() {
        TODO("Not yet implemented")
    }

    override fun action() {
        TODO("Not yet implemented")
    }
}

fun main() {
    MeituanLoginView().startView()

}

接口

/**
 * 接口的作用:统一接口
 *          在一个类中植入已知方法
 *          数据回调  A -> B
 * 投影仪 -> HDMI接口 ——> 电脑
 * 品牌很多
 */


interface HDMIOutputInterface{
    //接口中的方法如没有实现 则默认是抽象方法
    fun outputData(data:String)
}

class Projector:HDMIOutputInterface{
    val brand = "索尼"
    override fun outputData(data: String) {
        println("我是${brand} 接收到数据:$data")
    }
}

class Computer{
    fun enter(){
        val projector:HDMIOutputInterface = Projector()
        projector.outputData("画面 ")
    }
}

fun main() {
    Computer().enter()
}

设计模式

MVC设计模式(安卓默认)
  • M :Model: 数据业务

    ​ 把数据相关处理的用一个类封装,要用时直接访问这个类就行了

  • V :View : layout布局文件 :按钮 文本 图片

  • C :Controller: Activity 控制View和Model之间数据传递

好处:分离 复用性强

弊端:循环引用 ,可能出现无法释放对象 ——> 弱引用 或 变成局部变量,降低作用域

MVP设计模式

​ View将数据传递给Presenter,在Presenter中通过调用Model处理数据,再通过定义好的接口,将数据传递给View

  • M :Model 专门处理数据

  • V : View Activity

  • P : Presenter 处Model和View的数据交互 通常需要一个接口来定义一些方法

VIew -> (interface)Present -> Model

灵活,使Activity更简洁,一个界面对应一个接口,文件较大,结构复杂

匿名类

语法:object: 类名/接口 {

}

当需要一个类的子类或抽象类或接口的实现类

  • 匿名类/对象 -> ,创建的对象只需要使用一次

  • 普通类 -> 有名字,这给类会被多次使用

​ 注:构建子类时会先构建父类

    //用一个类实现OnClickListener接口
    //这个类会被多次使用
    test(Button())

    //没有创建一个类继承于这个接口
    //匿名类/对象
    //只需要使用一次
    test(object: OnClickListener{
        override fun onClick(obj: Any) {
            println("按钮被点击了")
        }
    })
Lambda表达式

Java中,如果参数里面时接口类型,且接口类型里面只有一个方法,满足了lambda表达式

public class MyTestLmabda {
	public static void main(String[] args) {
		test(obj -> {
			//具体的实现
		})
	}
}

public static void test(BtnClick l) {

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值