Kotlin学习笔记2---基础语法

183 阅读5分钟

本课程为极客时间上朱涛老师的《Kotlin编程第一课》的学习笔记

1.变量

  • val 不可变,相当于Java中加了final
  • var可变
/*
关键字     变量类型
 ↓          ↓           */
var price: Int = 100;   /*
     ↑            ↑
   变量名        变量值   */

由于Kotlin支持类型推导,所以还可以进一步略写

var price = 100 // 默认推导类型为: Int

PS:好习惯就是尽量用val而不是var,合理利用kotlin的优势,能避免很多问题

2.基础类型

Kotlin中,一起都是对象

Java中存在 int,short这样的基础类型;Kotlin则没有这些基础类型;

并且Java中有自动装包和自动拆包;这就是为了解决基础类型和数据类之间转换的问题;而Kotlin从设计之初就避免了这个问题

基础类型分为两类:

  • 原始类型(Primitive Types):如int,long
  • 包装类型(Wrapper Type):如Interger,Long

3.空安全

val i: Double = null // 编译器报错

这样的写法是不合理的,Kotlin会要求开发者在定义前指定变量是否为空;这种策略极大避免了空指针NullPointException;

所以正确的写法如下:

val i: Double = null // 编译器报错
val j: Double? = null // 编译通过

4.数字类型

Java可以隐藏式抓换数字类型,而kotlin更推崇显式转换

例如,下面的表达式在Java中是正常的

int i = 100;
long j = i;

但是在kotlin中就会报异常:

val i = 100
val j: Long = i // 编译器报错

需要更改为以下格式才行:

val i = 100
val j: Long = i.toLong() // 编译通过

特点就是:可读性更强,维护性更强;并且充分发挥了Kotlin没有基础类型的优势

5.布尔类型

Kotlin中布尔类型的变量,只有两种值,分别是true和false;这里主要讲Kotlin中的一些逻辑操作

  • “&”代表“与运算”;
  • “|”代表“或运算”;
  • “!”代表“非运算”;
  • “&&”和“||”分别代表它们对应的“短路逻辑运算”。

例如:

val i = 1
val j = 2
val k = 3

val isTrue: Boolean = i < j && j < k

6.字符

字符用于单个字符val c: Char = 'A'

但是下面的按照Java和C的方式写的代码,就会报错

val c: Char = 'A'
val i: Int = c // 编译器报错

原因就是前面隐式转换一样的问题,Kotlin并不支持隐式转换;所以正确的操作是这样的

val c: Char = 'A'
val i: Int = c.toInt() // 编译通过

7.字符串:String

字符串,顾名思意,就是一连串的字符。但是kotlin的拓展能力会令开发这觉得很方便

  • 简洁模板
val name = "Kotlin"
print("Hello $name!")
/*            ↑
    直接在字符串中访问变量,这个特性在js,python已经存在;Java至今没有适配
*/
// 输出结果:
Hello Kotlin!
  • 带方法的模板
val array = arrayOf("Java", "Kotlin")
print("Hello ${array.get(1)}!")
/*            ↑
      复杂的变量,使用${}
*/
// 输出结果:
Hello Kotlin!
  • 原始字符串(解决转义的神器)
val s = """
       当我们的字符串有复杂的格式时
       原始字符串非常的方便
       因为它可以做到所见即所得。 """

print(s)

8.数组

相对于Java,Kotlin中的数组会更丰富

  • 使用arrayOf来创建数组
val arrayInt = arrayOf(1, 2, 3)
val arrayString = arrayOf("apple", "pear")

虽然 Kotlin 的数组仍然不属于集合,但它的一些操作是跟集合统一的。

val array = arrayOf("apple", "pear")
println("Size is ${array.size}")
println("First element is ${array[0]}")

// 输出结果:
Size is 2
First element is apple

9.函数(最高公民)

  • 函数的声明
    • 使用了 fun 关键字来定义函数;
    • 函数名称,使用的是驼峰命名法(大部分情况下);
    • 函数参数,是以 (name: String) 这样的形式传递的,这代表了参数类型为 String 类型;
    • 返回值类型,紧跟在参数的后面;
    • 最后是花括号内的函数体,它代表了整个函数的逻辑
/*
关键字    函数名          参数类型   返回值类型
 ↓        ↓                ↓       ↓      */
fun helloFunction(name: String): String {
    return "Hello $name !"
}/*   ↑
   花括号内为:函数体
*/

上面的格式为标准格式,其实在实际使用会存在简化格式;如上面的可以简化为单一表达表函数

fun helloFunction(name: String): String = "Hello $name !"

而且在单一表达形式的时候,返回值类型也可以省略;这里也是利用了类型推导

fun helloFunction(name: String) = "Hello $name !"

10.函数的调用

  • 标准的函数调用
helloFunction("Kotlin")
  • 使用命名参数
helloFunction(name = "Kotlin")比较复杂的场景

使用场景

fun createUser(
    name: String,
    age: Int,
    gender: Int,
    friendCount: Int,
    feedCount: Int,
    likeCount: Long,
    commentCount: Int
) {
    //..
}
  • 参数默认值
fun createUser(
    name: String,
    age: Int,
    gender: Int = 1,
    friendCount: Int = 0,
    feedCount: Int = 0,
    likeCount: Long = 0L,
    commentCount: Int = 0
) {
    //..
}

默认参数的好处就是如果不传入值,会填入默认值

11.流程控制

11.1 if

if语句,在程序中主要是用于逻辑判断,Kotlin中if与Java一致

val i = 1
if (i > 0) {
    print("Big")
} else {
    print("Small")
}

输出结果:
Big

当然这个是仿Java的写法,Kotlin还有更简洁的写法

val i = 1
val message = if (i > 0) "Big" else "Small"

print(message)

输出结果:
Big

Elvis表达式 :超强的可空判断

fun getLength(text: String?): Int {
  return text?.length ?: 0
}

它的效果等同于

if (xxx != null) xxx else xxx

它的特点就在于:提高了的代码的可读性,也提升了编码效率

11.2when

when的使用场景在于,代码逻辑存在多个分支时,使用它是最稳妥的;个人感觉比if/else if/if的组合要好很多

val i: Int = 1

when(i) {
    1 -> print("一")
    2 -> print("二")
    else -> print("i 不是一也不是二")
}

输出结果:
一

同样的,它也具备简写的方式

val i: Int = 1

val message = when(i) {
    1 -> "一"
    2 -> "二"
    else -> "i 不是一也不是二" // 如果去掉这行,会报错
}

print(message)

注意:when必须要枚举完所有可能出现的参数,所以这里就不能去掉else;但是如果when条件已经枚举完;不需要写else的情况下时,需要特殊的操作(具体什么,后面会说)

11.3while 与 for

两者都是重复执行代码体内的参数,普while通写法与Java没什么区别

var i = 0
while (i <= 2) {
    println(i)
    i++
}

var j = 0
do {
    println(j)
    j++
} while (j <= 2)

输出结果:
0
1
2
0
1
2

但是for的语句就不相同,更多用于“迭代”的概念

val array = arrayOf(1, 2, 3)
for (i in array) {
    println(i)
}
//上面的代码用来迭代打印array这个数组内所有的元素

迭代一个区间用到“..”来连接数值区间的两端

val oneToThree = 1..3 // 代表 [1, 3]
for (i in oneToThree) {
    println(i)
}

输出结果:
1
2
3

甚至可以使用逆序迭代一个区间

for (i in 6 downTo 0 step 2) {
    println(i)
}

输出结果:
6
4
2
0

这里只能如此定义(感觉怪怪的),而且“6..0”这样的定义是无效的

12.章节小结

img