Kotlin 基础(一)

1. 标识符

特定标识符field和it。在Kotlin语言中有两个由编译器定义的特定标识符,它们只能在特定场景中使用有特定的作用,而在其他的场景中可以做标识符使用。

提示:field标识符用于属性访问器中,访问属性支持字段;it标识符用于Lambda表达式中,在省略参数列表时作为隐式参数,即不需要声明就可以使用的参数。

    // 创建一个字符串数组
    var arrays = arrayListOf("A", "B", "C")
    // 遍历
    arrays.forEach { println(it) }

2. 关键字

Kotlin语言中有70多个关键字,全部是小写英文字母,以及!和?等字符构成。分为3个大类:

硬关键字(Hard Keywords),硬关键字任何情况下都不能作为标识符,具体包括如下关键字。

as、as?、break、class、continue、do、else、false、for、fun、if、in、!in、interface、is、!is、null、object、package、      return、super、this、throw、true、try、typealias、val、var、when和while。

软关键字(Soft Keywords),是在它适用场景中不能作为标识符,而其他场景中可以作为标识符,具体包括如下关键字。

by、catch、constructor、delegate、dynamic、field、file、finally、get、import、init、param、property、receiver、set、
setparam和where。

修饰符关键字(Modifier Keywords),修饰符关键字是一种特殊的软关键字,它们用来修饰函数、类、接口、参数和属性等内容,在此场景中不能作为标识符。而其他场景中可以作为标识符,具体包括如下关键字。

abstract、annotation、companion、const、crossinline、data、enum、external、final、infix、inner、internal、lateinit、
noinline、open、operator、out、override、private、protected、public、reified、sealed、suspend、tailrec和vararg。

3. 变量和常量

1. 变量

 在Kotlin中声明变量,就是在标识符的前面加上关键字var。

var str = "kotlin"
var i = 0
var price: Float = 10.08f

2. 常量和只读变量

常量和只读变量一旦初始化后就不能再被修改。在Kotlin声明常量是在标识符的前面加上val或const val关键字.

它们的区别如下。

val声明的是运行期常量,常量是在运行时初始化的

const val声明的是编译期常量,常量是在编译时初始化,只能用于顶层常量声明或声明对象中的常量声明,而且只能是String      或基本数据类型(整数、浮点等)。

提示: 编译期常量(const val)相当于Java中public final static所修饰的常量。而运行期常量(val)相当于Java中final所修饰的    常量。

const val str = "compile kotlin"   // 申明顶层常量

//声明对象
object UserDAO {
    const val MAX_COUNT = 100 // 对象中的声明常量 
}

fun main(args: Array<String>) {
    val price: Float = 0.0f 
    val y = 20 
}

 约定: 常量其实就是只读变量,编译期常量(const val)是更为彻底的常量,一旦编译之后就不能再修改了。而运行期常(val)还可以根据程序的运行情况初始化。

使用var还是val?

原则: 如果两种方式都能满足需求情况下,原则上优先考虑使用val声明。因为一方面val声明的变量是只读,一旦初始化后不  能修改,这可以避免程序运行过程中错误地修改变量内容;另一方面在声明引用类型使用val,对象的引用不会被修改,但是
引用内容可以修改,这样会更加安全,也符合函数式编程的技术要求。

4. 表达式

    val score = 80
    // if控制结构表达式
    val result = if (score < 60) "不及格" else "及格"

    //try表达式
    val score = try {
        //TODO
    } catch (e: Exception) {
        return
    }

5. 类的声明

data class Order(var id: Long, var date: Date)

6. Unit

如果一个函数的返回类型是Unit,则需要省略。Kotlin的Unit关键字相当于Java中的void,表示返回空的数据,用于函数的返回     类型声明.

7. 基本数据类型

整数类型:Byte、Short、Int和Long,Int是默认类型。
浮点类型:Float和Double,Double是默认类型。
字符类型:Char。
布尔类型:Boolean。

8. 非空类型和可空类型

Kotlin语言,默认情况下所有的数据类型都是非空类型(Non-Null),声明的变量都是不能接收空值(null)的。

var n: Int = 10
n = null //发生编译错误

Kotlin为每一种非空类型提供对应的可空类型(Nullable),就是在非空类型后面加上问号(?)表示可空类型。

var n: Int? = 10
n = null //可以接收空值(null)

可空类型在具体使用时会有一些限制:   

不能直接调用可空类型对象的函数或属性。
不能把可空类型数据赋值给非空类型变量。
不能把可空类型数据传递给非空类型参数的函数。

为了“突破”这些限制,Kotlin提供了如下运算符:
安全调用运算符:?.

可空类型变量使用安全调用运算符(?.)可以调用非空类型的函数或属性。安全调用运算符(?.)会判断可空类型变量是否为空,如果是则不会调用函数或属性,直接返回空值;否则返回调用结果。

fun main(args: Array<String>) {
    
    val divNumber1 = divide(100, 0)
    val result1 = divNumber1?.plus(100)  //divNumber1+100,结果null 
    println(result1)
    val divNumber2 = divide(100, 10)
    val result2 = divNumber2?.plus(100)  //divNumber2+100,结果110.0 
    println(result2)

}

//声明除法运算函数
fun divide(n1: Int, n2: Int): Double? {
    if (n2 == 0) {//判断分母是否为0
        return null
    }
    return n1.toDouble() / n2
}

安全转换运算符:as?
Elvis运算符:?:

有的时候在可空类型表达式中,当表达式为空值时,并不希望返回默认的空值,而是其他数值。此时可以使用Elvis运算符          (?:),也称为空值合并运算符,Elvis运算符有两个操作数,假设有表达式:A ?: B,如果A不为空值则结果为A;否则结            果为B。

fun main(args: Array<String>) {
    
    val divNumber1 = divide(100, 0)
    val result1 = divNumber1?.plus(100) ?: 0   //divNumber1+100,结果0 
    println(result1)
    val divNumber2 = divide(100, 10)
    val result2 = divNumber2?.plus(100) ?: 0   //divNumber2+100,结果110.0 
    println(result2)

}

//声明除法运算函数
fun divide(n1: Int, n2: Int): Double? {
    if (n2 == 0) {//判断分母是否为0
        return null
    }
    return n1.toDouble() / n2
}

非空断言:!!

可空类型变量可以使用非空断言运算符(!!)调用非空类型的函数或属性。非空断言运算符(!!)顾名思义就是断言可空类          型变量不会为空,调用过程是存在风险的,如果可空类型变量真的为空,则会抛出空指针异常;如果非则可以正常调用函            数或属性。

fun main(args: Array<String>) {
    
    val divNumber1 = divide(100, 10)
    val result1 = divNumber1!!.plus(100)   //divNumber1+100,结果110.0
    println(result1)
    val divNumber2 = divide(100, 0)
    val result2 = divNumber2!!.plus(100)  //divNumber2+100,结果抛出异常 
    println(result2)

}

//声明除法运算函数
fun divide(n1: Int, n2: Int): Double? {
    if (n2 == 0) {//判断分母是否为0
        return null
    }
    return n1.toDouble() / n2
}

此外,还一个let函数帮助处理可空类型数据。

9. 字符串模板

字符串模板是以$开头,语法如下:

$变量或常量
${表达式} //任何表达式,也可以是单个变量或常量

val age = 18
val s1 = "她的年龄是${age}岁。" //使用表达式形式模板 
println(s1) //她的年龄是18岁。
val score = 'A'
val s2 = "她的英语成绩是$score" //使用变量形式模板
println(s2) //她的英语成绩是A
val now = java.util.Date()
val s3 = "今天是:${now.year + 1900}年${now.month}月${now.day}日" ③
println(s3)

10 . 其它运算符

冒号(:)。用于变量或常量类型声明,以及声明继承父类和实现接口。
小括号。起到改变表达式运算顺序的作用,它的优先级最高。
中括号([])。索引访问运算符号。
引用号(.)。调用函数或属性运算符。
赋值号(=)。赋值是用等号运算符(=)进行的。
可空符(?)。标识一个可空类型。
安全调用运算符(?.)。调用非空类型的函数或属性。
Elvis运算符(?:)。空值合并运算符。
非空断言(!!)。断言可空表达式为非空。
双冒号(::)。引用类、属性或函数。
区间(..)。表示一个范围区间。
箭头(->)。用来声明Lambda表达式。
展开运算符(*)。将数组传递给可变参数时使用

运算符优先级大体顺序,从高到低是:算术运算符→位运算符→关系运算符→逻辑运算符→赋值运算符。

11. 程序流程控制

分支结构:if和when

循环结构:while、do-while和for

跳转结构:break、continue和return

when多分支结构:

1. when结构当做语句使用

when (表达式) {
    分支条件表达式1 -> {
        语句组1
    }
    分支条件表达式2 -> {
        语句组2
    }
    ...
    分支条件表达式n -> {
        语句组n
    }
    else -> {
        语句组n+1
    }
}
fun main(args: Array<String>) {
    val testScore = 75 //设定一个数值用来测试
    when (testScore / 10) { 
        9 -> { 
            println('优')
        }
        8 -> println('良')
        7, 6 -> println('中') 
        else -> println('差')
    }
    val level = "优" //设定一个数值用来测试
    var desc = "" //接收返回值
    when (level) { 
        "优" -> desc = "90分以上"
        "良" -> desc = "80分~90分"
        "中" -> desc = "70分~80分"
        "差" -> desc = "低于60分"
    }
    println("说明 = " + desc)
}

break 配合标签使用

label1@ for (x in 0..4) { 
    for (y in 5 downTo 1) { 
        if (y == x) {
            // 跳转到label1指向的外循环
            break@label1 
        }
        println("(x,y) = ($x,$y)")
    }
}
println("Game Over!")

Kotlin核心库中有三个闭区间类:IntRange、LongRange和CharRange

区间中的元素只能是整数或字符,不能是浮点、字符串等其他数据类型。

在Kotlin语言中闭区间采用区间运算符(..)表示,而半开区间则需要使用中缀运算符until表示。

fun main(args: Array<String>) {
    for (x in 0..5) { //定义闭区间包含0和5 
        print("$x,")
    }
    println()
    for (x in 0 until 5) { //定义半开区间包含0,不包含5 
        print("$x,")
    }
    println()
    for (x in 'A'..'E') { //定义闭区间包含'A'和'E' 
        print("$x,")
    }
    println()
    for (x in 'A' until 'E') { //定义半开区间包含'A',不包含'E' 
        print("$x,")
    }
}

12. 使用in和!in关键字

判断一个数值是否在区间中可以使用in关键字。而!in关键字,则是判断一个值不在区间中。此外,这两个关键字(in和!in)还      可以判断一个数值是否集合或数组中。

fun main(args: Array<String>) {
    var testscore = 80 //设置一个分数用于测试
    var grade = when (testscore) { 
        in 90..100 -> "优"
        in 80 until 90 -> "良"
        in 60 until 80 -> "中"
        in 0 until 60 -> "差"
        else -> "无"
    } 
    println("Grade = " + grade)
    if (testscore !in 60..100) { //使用!in关键字 
        println("不及格")
    }
    val strArray = arrayOf("刘备", "关羽", "张飞")
    val name = "赵云"
    if (name !in strArray) { 
        println(name + "不在队伍中")
    }
}

13. 函数

fun 函数名(参数列表) : 返回值类型 {
    函数体
    return 返回值
}

无返回数据与Unit类型

有的函数只是为了处理某个过程,不需要返回具体数据,例如println函数。此时可以将函数返回类型声明为Unit,相当于Java      中的void类型,即表示没有实际意义的数据。  

fun printArea2(width: Double, height: Double) { //省略Unit 
    val area = width * height
    println("$width x $height 长方形的面积:$area")
    //省略return 
}

永远不会正常返回数据与Nothing类型

Kotlin中提供一种特殊的数据类型Nothing,Nothing只用于函数返回类型声明,不能用于变量声明。Nothing声明的函数永远不  会正常的返回,只会抛出异常。

fun readDate(): Nothing {
    throw IOException()
}

提示: 使用Nothing的目的何在?有些框架,例如Junit单元测试框架,在测试失败时会调用Nothing返回类型的函数,通过它抛出异常使当前测试用例失败。

注意 Unit与Nothing区别?Unit表示数据没有实际意义,它可以声明函数返回类型,也可以声明变量类型,声明函数时函数可以正常返回,只是返回数据没有实际意义。Nothing只能声明函数返回类型,说明函数永远不会正常返回,Nothing不能声
明变量。

可变参数

Kotlin中函数的参数个数可以变化,它可以接受不确定数量的输入类型参数(这些参数具有相同的类型),有点像是传递一个数组。可以通过在参数名前面加vararg关键字的方式来表示这是可变参数。

fun sum(vararg numbers: Double, multiple: Int = 1): Double {
    var total = 0.0
    for (number in numbers) {
        total += number
    }
    return total * multiple
}

表达式函数体

fun rectangleArea(width: Double, height: Double) = width * height

Kotlin中的类成员包括:
构造函数
初始化代码块
成员函数
属性
内部类和嵌套类
对象表达式声明

// 员工类
class Employee {
    var no: Int = 0 // 员工编号属性
    var job: String? = null // 工作属性 
    var firstName: String = "Tony" 
    var lastName: String = "Guan" 
    var fullName: String //全名 
        get() { 
            return firstName + "." + lastName
        }
        set (value) { 
            val name = value.split(".") 
            firstName = name[0]
            lastName = name[1]
        }
    var salary: Double = 0.0 // 薪资属性 
        set(value) {
            if (value >= 0.0) field = value 
        }
}

提示: 属性本身并不真正的保存数据,数据被保存到支持字段中,支持字段一般是不可见的,支持字段只能应用在属性访问器中,通过系统定义好的field变量访问。

提示: 并不是所有的属性都有支持字段的,例如上述代码中的fullName属性是通过另外属性计算而来,它没有支持字段,声明时不需要初始值。这种属性有点像是一个函数。这种属性在Swift语言中称为计算属性。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值