Kotlin学习笔记---持续更新中

1.程序入口

fun main(args:Array<String>){
    println("hello world");
}

fun:函数的声明,固定写法

main:程序的入口

args:接受的参数,数据类型字符串

2.变量和输出

  1. 变量的声明

    var name="张三" //变量声明关键词var,语句末尾不需要分号
    
  2. 数据类型

    类型 范围
    Byte 整数-128~127
    Short 整数-32768~32767
    Int 整数-2147483648~2147483647
    Long 整数-9223372036854775807~9223372036854775806
    Float 小数,小数点可以精确到6位
    Double 小数,小数点可以精确到15-16位
    String 字符串,用双引号引起来的字符串都可以存
    3.类型推断和显示类型声明
    1. 类型推断

      • 在声明一个变量时,我们可以不需要显示声明数据类型,kotlin会根据你为变量赋的值动态地推导出其类型

      • 当一个变量被赋予了某个类型的数值之后,不能再赋给他其他类型的数值,否则,会报类型错误

        fun main(args:Array<String>){
            var a=10    //声明变量a , 将int类型的10 赋值给a, a 将只能接受int型数据
            a=15
        
            //a="字符串"   //将字符串类型的数据赋值给int型的a ,报错!!
        
            var s="字符串"
        }
        
    2. 显示类型声明

      格式:var变量名:变量类型=值

      var a:Int=10 
      
    3. 变量声明的注意事项

      • 如果声明变量时就赋初值,可以不写类型,此时,类型推导将生效
      • 如果声明变量时没有赋初值,则必须写明类型,否则会报错。格式:var a:Int
    4. 常量的声明

      关键字:val

      格式:val 常量名:常量类型=常量值

3.变量的取值范围

获取某种类型数据的最大最小值

fun main(args:Array<String>){
    val minByte:Byte=Byte.MIN_VALUE
    val maxByte:Byte=Byte.MAX_VALUE

    val a:Int=0b0011    //将二进制的0b0011 转换为10进制,并复制给a 
}
  • Byte、Int、Long可以通过上述方式获取最大最小值
  • String没有最大最小值,所以没有上述方法

4.Kotlin函数入门

  • main() 程序入口
  • println() 打印

函数声明基本格式:fun 函数名(参数:参数类型){函数体}

5.字符串模板

  • “”,被两个双引号包裹的内容是普通字符串,支持转义符
  • “”" “”",被一对三引号包裹的内容是原样字符串,不支持转义字符,其中的内容被定义成什么样,输出的时候就是什么样
  • 字符串模板格式:${占位字符串}

6.字符串比较

  • 可以使用 == 比较字符串
  • 也可以使用equals(,)方法比较字符串,该方法第二个参数表示是否忽略大小写,true–忽略,false–不忽略
    • equals(,)中第二个参数为true时,效果等价于Java中的equalsIgnoreCase()

7.空值处理

  • 以null表示空值
  • kotlin中定义方法时,默认接收的是非null参数
  • 如果定义某个方法可以接收null参数,则在声明方法参数时在参数后面加上**?**

8.When表达式

类似于Java中的switch,基本使用格式:

when(变量){
    分支A -> 表达式
    else -> 表达式
}

带有返回值的When表达式

var result=when(变量){
    分支A -> 表达式(要有返回值,最终将值赋给result)
    else -> 表达式(要有返回值,最终将值赋给result)
}

9.Loop和Range

  • 声明一个区间数组

    var nums1=1..100  //表示我们声明了一个闭区间数组,其中包含的数值为 1-100。 .. 表示闭区间
    var nums2=1 util 100 //前闭后开区间,取值 1-99. util 表示前闭后开区间
    
  • for基本循环格式

    for(变量 in 数组或字符串){
        //DO STH 
    }
    
  • 带有步进的for循环

    for (变量 in 数组 step 步进数量){    //所谓步进,就是递增幅度。默认步进为1
        //DO STH 
    }
    
  • 数组.reversed() //数组内容反转

  • 数组.count() //获取数组的容量,等价于Java中的数组.length

10.List和Map

  1. List

    • List的基本声明格式:

      var list1=listOf(元素1,元素2,元素3)    //声明List时主要是通过 listOf()实现
      
    • 使用for循环同时遍历索引和索引对应的数值

      for(index,value) in list.withIndex(){    //重点是 withIndex() 方法,index 接收索引,value 接收对应的值
          //DO  STH 
      }
      
  2. Map(词典)

    • 基本声明格式

      var map=TreeMap<键类型,值类型>()
      map[key]=value
      
    • 示例代码

      var map=TreeMap<String,String>()    //声明 map
      map["好"]=good
      map["学习"]=study    //添加键值对元素
      
      println(map["好"])    //取值并打印
      

11.函数和函数表达式

  1. 函数的简化

    //原函数:
    fun sum(a:Int , b:Int):Int{
        return a+b
    }
    
    //简化后
    fun sum(a:Int , b:Int):Int=a+b
    
  2. 使用var声明函数–函数表达式1

    kotlin 中除了使用基本的 fun 关键字声明函数外,还可以使用 var 声明。示例如下:

    var i={x:Int , y:Int -> x+y} //声明函数i,接收两个Int类型参数 x、y,返回 x+y 的值
    i(3,5) //调用使用 var 声明的函数 i
    
  3. 使用var声明函数–函数表达式2

    var j:(Int,Int)->Int={x,y -> x+y}   //声明函数j,它接收的参数是两个Int, 返回一个Int,对应的表达式是 {x,y->x+y}
    j(4,4)    //调用函数
    

12.默认参数和具名参数

  • 具有默认参数值的函数声明

    val Pi=3.1415926
    fun getRoundArea(PI:Float=Pi , radius:Float):Float{    //为变量PI赋予了默认值 Pi,这样,调用该方法时可以不再传递PI。但,如果我们想传入的值和默认值不一致时还是需要传入的
        return PI*radius*radius
    }
    
  • 调用带有默认参数值的函数

    var a=getRoundArea(3.14f,5.0f) //因为我们相传入的PI和默认值不一致,所以,需要将3.14f传入
    
  • 具名参数的使用

    所谓具名参数,就是调用某个方法时指明传入的参数是给哪个变量的

    var a=getRoundArea(radius=5.0f) //我们需要的PI值与默认值一致,此时不需要再传入PI值。只需要通过 radius=5.0f 声明我们传入了半径值
    

13.字符串和数字的转换

var a="13"
a.toInt()    //字符串转换为Int

var b=13
b.toString()    //Int转换为字符串

14.异常处理–同Java

try{
    //可能会出错的代码块
}catch(e:Excepiton){
    //出错之后的处理逻辑
}

15.递归

  1. 利用递归实现阶乘函数

    fun fact(a:Int):Int{
        if(a==1){
            return 1
        }else{
            return a*fact(a-1) //函数内调用函数本身就成为了递归
        }
    }
    
  2. BigInteger

    在上面的方法中,我们用Int来接收阶乘的值,但如果超出了Int的范围,就会返回0.所以这时候就需要用到BitInteger。BitInteger用来表示一个超大值。

    import java.math.BigInteger
    
    fun main(array: Array<String>) {
        val num = BigInteger("50")    //声明BigInteger常量时传入一个字符串类型的数值
        println(fact(num))
    }
    
    fun fact(num: BigInteger): BigInteger {
        return if (num == BigInteger.ONE) {
            BigInteger.ONE
        } else {
            num * fact(num - BigInteger.ONE)
        }
    }
    

16.尾递归优化

  1. 什么是尾递归

    • 尾递归:是指某个函数的最后一步依旧是调用自身
    • kotlin中尾递归关键字tailrec
  2. 为什么需要尾递归优化

    递归非常耗费内存,因为需要同时保存成千上百个调用记录,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用记录,所以永远不会发生栈溢出错误。

  3. 使用尾递归实现累加

    fun main(args: Array<String>) {
        println(accumulation(5, 1))
    }
    
    /**
     * tailrec 是尾递归函数的关键字
     * 尾递归函数是指,在该函数的最后一步操作中依旧是调用函数本身
     * 为了实现尾递归,我们定义了该方法接收两个参数:num 是我们传入的需要计算累加值得的变量,total用来接收最终的返回值
     */
    tailrec fun accumulation(num: Int, total: Int): Int {
        return if (num == 1) {
            total
        } else {
            accumulation(num - 1, num + total)  //此时,该调用的含义是:先计算 total=num+total,然后计算 num=num-1
        }
    }
    

17.面向对象入门-定义一个类并构建对象

//定义一个类,包含两个成员变量 height和width
class Rect(var height:Int,var width:Int)

fun main(args: Array<String>) {
    var rect=Rect(5,10) //构建Rect对象,不需要new
    println("矩形的宽${rect.width}${rect.height}") //引用Rect类中成员变量
}

18.静态属性和动态行为/方法-为类定义成员方法

//定义一个类,包含两个成员变量 height和width.并定义一个成员方法
class Rect(var height: Int, var width: Int) {
    fun getArea(a: Int, b: Int): Int = a * b
}

fun main(args: Array<String>) {
    var rect = Rect(5, 10) //构建Rect对象,不需要new
    println("矩形的宽${rect.width}${rect.height}") //引用Rect类中成员变量
    println("矩形的面积是${rect.getArea(rect.width, rect.height)}") //引用Rect类中成员变量

}

19.面向对象-继承

  • 一个对象直接使用另一个对象的属性或方法-同Java
  • 被继承的父类必须用open修饰,表示允许其他类继承该类
  • 父类中的方法如果允许子类重写,也需要用open修饰
  • 重写父类方法时需要用override修饰重写后的方法
  • 继承的格式:class 子类:父类()

父类:

open class Father {    //用 open 修饰,允许被继承
    var character = "性格内向"
    open fun action() {    //用open修饰,允许被重写
        println("喜欢读书")
    }
}

子类:

class Son : Father() {    //继承。 Son 继承自 Father
    override fun action() {    //重写父类方法
        //super.action()
        println("儿子的性格是$character")   
        println("儿子不喜欢看书,但是喜欢唱歌")
    }
}

20.抽象类及其实现

  • 抽象类的关键字:abstract–同Java
  • 抽象类和方法不需要用open声明可以被继承/实现

抽象类Human:

abstract class Human (var name: String){      //定义抽象类,使用 abstract 修饰。包含成员变量name
    abstract fun eat()      //定义抽象方法, 使用 abstract 修饰
}

抽象类的子类Man:

class Man(name: String) : Human(name) {    //继承自Human抽象类
    override fun eat() {    //必须重写抽象方法
        println("${name}是男人,是家中劳力,所以吃的多")
    }
}

调用子类:

fun main(args: Array<String>) {
    var man=Man("张三")
    man.eat()
}

21.接口及其实现

  • 接口–数据有进有出的交互方式
  • 接口关键字–interface,同Java
  • 接口是事物的能力(代表某种事物的特性),抽象类是事物的本质(代表的是一类事物的共性)
  • 子类实现接口时,接口名后面不需要()

定义接口IMan

interface IMan {    //定义一个男人的接口
    fun xiaodidi()
}

Man类实现IMan接口

class Man(name: String) : Human(name) ,IMan{  //男人属于人,所以继承Human;男人有小弟弟,所以实现 IMan接口
    override fun xiaodidi() {
        println("这是重写IMan接口中的方法——男人有小弟弟")
    }

    override fun pee() {
        println("${name}是男人,是站着尿尿的")
    }

    override fun eat() {
        println("${name}是男人,是家中劳力,所以吃的多")
    }
}

22.代理和委托–大头儿子和小头爸爸的洗碗案例

  • 委托,把自己不干的事情交给别人做
  • 代理,做别人委托的事情
  • kotlin中接口代理关键字:by
  1. 场景说明

    围裙妈妈只负责做饭,不负责洗碗
    小头爸爸洗一次碗可以赚到10元
    大头儿子洗一次碗可以赚到1元
    小头爸爸承揽了洗碗的活,最终交给大头儿子做,中间赚了9元差价
    
  2. 代码实现–完全委托

    • 定义洗碗的接口

      interface IWashBow {    //定义一个洗碗接口,包含一个洗碗方法
          fun washBow()
      }
      
    • 大头儿子实现接口

      class BigHeadSon:IWashBow {    //被实现的接口后面不需要加()
          override fun washBow() {
              println("我是大头儿子,每次洗碗赚1元钱")
          }
      }
      
    • 小头爸爸实现接口并委托时间给小头儿子

      class SmallHeadFather:IWashBow by BigHeadSon(){     //委托关键字 by;被委托方(即代理方)如果不是单例类,则后面需要跟()
      
      }
      
      fun main(args: Array<String>) {
          var father=SmallHeadFather()
          father.washBow()    //小头爸爸已经将洗碗的操作委托为小头儿子了,所以,此处本质是调用的小头儿子的洗碗操作
      }
      

23.单例模式

  • 单例关键字:object

    我们在定义一个类时,使用object替换class来修饰这个类,就表示这是一个单例类

  • 单例类作为代理人时,不需要()

  1. 场景说明

    小头爸爸为了增进父子感情,想和小头儿子一起洗碗
    
  2. 代码实现

    • 小头爸爸重写接口方法,未使用单例时的错误写法

      class SmallHeadFather:IWashBow by BigHeadSon(){    
      
          override fun washBow() {
              println("我是小头爸爸,我把洗碗事件委托给了大头儿子")
              BigHeadSon().washBow()  //委托方重写了事件之后,需要手动调用代理方的方法。但是,此处又通过()构建了一个小头儿子对象,已经不再是我们初始委托的那个大头儿子了。所以,此处是有问题的。
              println("我是小头爸爸,大头儿子洗完碗之后,我赚了9元")
          }
      }
      
    • 使用单例后的正确写法

      大头儿子单例类:

      object BigHeadSon:IWashBow {    //单例关键字object,声明为单例类之后会立即在内存中创建单例对象,并一直存在
          override fun washBow() {
              println("我是大头儿子,每次洗碗赚1元钱")
          }
      }
      

      小头爸爸委托事件给单例的大头儿子:

      class SmallHeadFather:IWashBow by BigHeadSon{     //被委托方(即代理方)是单例类,不需要通过()构建对象
      
          override fun washBow() {
              println("我是小头爸爸,虽然我把洗碗事件委托给了小头儿子,但是我要和他一起洗碗")
              BigHeadSon.washBow()  //委托方重写了事件之后,需要手动调用代理方的方法。由于 BigHeadSon是单例的,所以,这还是我们之前委托的那个儿子
              println("我是小头爸爸,我和小头儿子洗完碗之后,我赚了9元")
          }
      }
      
    • 外部调用

      fun main(args: Array<String>) {
          var father=SmallHeadFather()
          father.washBow()    //小头爸爸已经将洗碗的操作委托为小头儿子了,但因为重写了洗完事件,所以,本子是调用的父亲的洗完事件,父亲的洗完事件中有一部分是自己做的,另一部分是儿子做的
      }
      

24.枚举

枚举示例代码:

enum class Week {   //枚举关键字 enum 
    星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期天
}

fun main(args: Array<String>) {
    println(Week.星期一)
    println("${Week.星期一}在Week中的索引是${Week.星期一.ordinal}")
}

25.印章类/密封类(Sealed Class)

  1. 印章类的特点

    • 子类类型有限的类成为 印章类/密封类
    • 印章类使用 sealed 作为修饰符
    • 印章类本身没有构造方法
  2. 印章类与枚举的区别

    • 都是有限的数据
    • 枚举更注重具体的数据
    • 印章类更注重数据的类型
  3. 示例代码

    • 场景说明

      假设你家有一头公驴、一头母驴、一头公马。那么,
      它们可能会生出一头小驴,
      也可能会生出一头小骡子。
      
    • 代码示例

      在上述场景中,由于他们能生出的儿子类型时固定的,所以,我们可以使用印章类来标识。

      声明印章类

      sealed class Son {  //使用 sealed 声明 Son 为印章类/密封类
      
          class SmallMule() : Son()   //声明小骡子 SmallMule 为 Son的子类。
          class SmallDonkey() : Son() //声明小驴子 SmallDonkey 为 Son的子类
      
          fun sayHello(son: Son) {
              if (son is SmallMule) {     //判断是不是XX的实例的关键字 is 
                  println("小骡子对大家说大家好")
              } else if (son is SmallDonkey) {
                  println("小驴子对大家说大家好")
              }
          }
      }
      

      调用印章类

      fun main(args: Array<String>) {
          var mule = Son.SmallMule()
          var donkey = Son.SmallDonkey()
      
          var list = listOf<Son>(mule, donkey)
          for (son in list) {
              son.sayHello(son)
          }
      }
      

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