目录

Kotlin基础-语法

2011年JetBrains发布了Kotlin第一个版本; 2016年Kotlin发布了1.0正式版; 2017年Google宣布Kotlin成为Android一级开发语言.

基础知识

变量(varaibale)

val(value)用来声明一个不可变的变量, 对应Java中的Final. var(variable)用来声明一个可变的变量, 对应Java中的非Final.

// 完整的变量声明例子
val a: Int = 10

// Kotlin具有类型推导机制, 可以简化
val a = 10

Kotlin取消了Java的基本数据类型, 全部使用对象数据类型.

函数(function)

Java中多数称为方法(method). 声明方法需要fun关键字.

    // 函数的创建语法.
    fun 函数名称(参数1: 参数类型, 参数2: 参数类型): 返回值 {
        return 返回值
    }
    
    // 示例 完整版
    fun largerNumber(num1: Int, num2: Int): Int {
        return max(num1, num2)
    }

    // Kotlin语法糖
    // 当函数体只有一行代码时, 可以省略函数体{}, 将唯一一行代码
    // 定义到函数声明的尾部, 并用=连接
    fun largerNumber(num1: Int, num2: Int) : Int = max(num2, num1)
    
    // 由于推导机制, 返回值声明可以省略.
    fun largerNumber(num1: Int, num2: Int) = max(num2, num1)
    
    // 函数支持默认值, 上面函数可以添加默认
    fun largerNumber(num1: Int = 1, num2: Int = 2) = max(num2, num1)

逻辑控制语句

if条件语句

Kotlin的条件语句有两种: if, when

if语句和Java中的if几乎一模一样. 但Kotlin的if支持返回值, 就是每个条件的最后一行代码作为返回值.

when语句类似Java中的switch. 但不仅局限与Java的只能整型, 短整型,字符串

    // when语法结构
    when(变量){
        匹配值 -> {执行逻辑}
        匹配值 -> {执行逻辑}
    }
    
    // 示例 
    when(name){
        "张三" -> {"20岁"}
        "李四" -> {"21岁"}
        "王五" -> {"22岁"}
    }
    
    // 简化, 由于和if一样, 函数体最后一句最为返回值, 并且函数体只有一行代码
    // 可以省略{}
    when(name){
        "张三" -> "20岁"
        "李四" -> "21岁"
        "王五" -> "22岁"
    }

循环语句

  • while 与Java没有区别
  • for 舍弃了Java中的for-i循环, 对Java中的for-each进行增强, 并变成了for-in循环

区间概念: 正是由于没有了for-i的变量控制条件,才出现了区间概念

    // 创建一个0到100的区间
    var range = 0..100
    // 以上代码意思是. 一个0到100的区间, 并且两端都是闭区间, 也就是包含0和100.等价于数学中的
    // [0,100]

    // for-in 升序
    for (i in 1..100){
        println(i)
    }
    
    // 每次循环自增2
    for (i in 1..100 step){
        println(i)
    }
    

类和对象

  • Class 类, 同Java
  • File 通常用于编写Kotlin的顶层函数扩展函数
  • Interface 接口, 同Java
  • Enum class 枚举类
  • Object 数据类
    // 创建一个class类
    class Person{
    }
    
    // 获取Person示例, 不需要new
    var person = Person()

继承与构造函数

在Kotlin中任何一个非抽象类默认都是不可被继承的, 相当于Java中的String类添加了final关键字一样. 就如Effective java中提到的, 如果一个类不是为了专门继承而设计的, 就应该主动加上final. 而Kotlin把默认实现修改到final模式

那么如果要想一个类被继承, 使用open来修饰类.

    open class Person{}
    
    // Kotiln中使用 : 来代替Java中的extends
    class Student : Person(){}

Kotlin中有两种构造函数: 主构造函数, 次构造函数

一个类只能有一个主构造函数, 但是可以很多个次构造函数. 一个类默认有一个不带参的主构造函数 一个类如果仅有一个次构造函数, 那么此类是没有主构造函数

    // 主构造函数
    // 每个类默认有一个不带参数的主构造函数
    // 主构造函数特点是没有函数体, 只需在类名后显式的指明参数即可
    // 如果需要编写构造逻辑, 使用Kotlin提供的init结构体
    open class Person(age: Int, name:String){
        init {
            // 构造逻辑
        }
    }

    // 次构造函数
    // 当一个类既有主构造也有次构造, 那么所有的次构造都要调用主构造函数.
    open class Person(age: Int, name: String) {
        constructor() : this(11, "") {
        }

        constructor(age: Int, name: String, sex: Int) : this(age, name) {
        }
    }   
    

接口

同样使用**:**来实现接口继承, 并且被继承的类不需要追加括号, 因为接口没有构造函数.

允许对接口中定义的函数进行默认是实现. 这一特性在Java JDK1.8之后也同样支持.

函数可见性修饰符

修饰符 Java Kotlin
Public 所有类可见 所有类可见(默认)
private 当前类可见 当前类可见
protected 本类,子类,同一包路径可见 当前类,子类可见
default 同一包路径下的可见
internal 同一模块中的类可见

数据类型与单例类

    // 数据类实现 data关键字
    // 不再像Java一样需要实现equals(), hashCode(), toString()等方法
    data class schoolRool(val name:String, val id:Int)
    
    // 单例类  object关键字
    object Singleton{
    }

集合

使用内置函数listOf简化初始化集合的写法 val list = listOf("张三", "李四", "王五")

遍历集合 for(person in list){....}

listOf() 函数创建的是不可变集合, 即只读不能修改删除. mutableListOf() 函数与之对应, 可变集合.

setOf() mutableSetOf()

Map

Kotlin提供了一中类似数组下标的语法结构提供读写.

    val map = mutableMapOf("张三" to 1, "李四" to 2)
    map["王五"] = 3       // 赋值
    val age = map["李四"] // 取值

常用的一些函数式API

// 遍历集合元素, 并在函数体进行转换
list.map{ it.toUpperCase }

// 过滤集合, 进行筛选
list.filter{ it.lenght >= 5}

// 判断集合中是否至少存在一个元素满足条件
list.any { it.length >= 5 }

// 判断集合所有元素是否满足条件
list.all { it.length >= 5 }

Lambda

就是一小段可以作为参数传递的代码.

语法结构 {参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}

推导简化过程

        // 原始
        val list = listOf("apple", "pear", "banana")
        val lambda = { name: String -> name.length }  // lambda语句, 最后为单句省略了花括号
        val maxLength = list.maxOf (lambda)
        
        
        // 不需要定义lambda变量, 直接传入
        val maxLength = list.maxOf({ name: String -> name.length })
        
        // 当Lambda参数是函数的最后一个参数时,可以移到函数括号外面
        val maxLength = list.maxOf(){ name: String -> name.length }
         
        // 当Lambda参数是函数的唯一参数时, 可以去掉函数的括号
        val maxLength = list.maxOf{ name: String -> name.length }
        
        // 由于推导机制, Lambda的参数类型声明可以去掉
        val maxLength = list.maxOf{ name -> name.length }
        
        // 当Lambda表达式只有一个参数时, 不必声明参数, 使用it关键字代替
        val maxLength = list.maxOf{ it.length }

空指针

Kotlin默认所有的参数和变量都不可为空, 也就是说Kotlin将空指针异常的检查提前到了编译时期.

如果一个变量可空, 使用"?“关键字id Int?

判空辅助工具 person?.eat() 如果person为空就不调用eat()函数.

id?.lenght ?: 0 如果?:前为空就返回0, 否则不处理 ? : 逻辑

!! 非空断言

字符串内嵌表达式

"hi, ${person.name} "

当表达式中仅有一个变量的时候, 可以将两边的大括号省略.

关键字

  • is 相当于Java中的instanceof, 判断对象类型.
  • == 判断字符串或对象是否相等. 不再需要equals()专门判断字符串
  • .. 区间声明(升序), 两端都是闭区间, 也就是两端数字都包含, 等价于数学中*[0,100]*
  • until 区间声明(升序), 左闭右开区间, 包头不包尾,等价数学*[0,100)*
  • downTo 区间声明(降序), 两端都是闭区间, 包头包尾, 等价数学*[100,0]*
  • step 配合区间使用, 常规下区间是i++, i–,效果. 使用step 2, 实现循环中条件i=i+2的循环效果
  • class 声明类
  • open 修改类为可以被继承
  • : 类的继承关系指向
  • constructor 次构造函数声明
  • data 数据类型声明.
  • object 单例类声明
  • ?. 判空辅助工具 不空就调用
  • ?: 判空辅助工具 不空就返回
  • !! 非空断言