Kotlin学习记录——2.Kotlin基础
文章目录
- 1.基础数据类型
- 2.Kotlin变量声明方式
- 3.空安全
- 4.延迟属性 lazy
- 5.字符串
- 6.== 与 === 的区别
- 7.控制流
- 7.1 for循环
- 7.2 while循环
- 7.3 when循环
- 8.集合
- 8.1 数组
- 8.2 List
- 8.3 Map
- 9.函数
- 9.1 函数的定义
- 9.2 函数默认参数
- 9.3 函数具名参数
- 9.4 扩展函数
1.基础数据类型
在 Kotlin 语言中,所有的类型都是对象类型,Kotlin 中没有了 Java 中的基础数据类型(int、boolean、char、byte)等,全部换为对象类型。Kotlin 中类型如下:
- Int
- Boolean
- Byte
- Float
- Char
- Double
- Short
这些与 Java 中的数据类型是等价的(Integer,Boolean ,Byte,Float,Double ),但这些没有了 Java 中隐式拓宽转换,例如不能把 Int 类型直接赋值给 Long , 或者 Float 类型了,如要要这样做可以调用如下方法进行转换:
let a = 3
let b = a.toFloat() //b这时的类型为 Float 类型
基本的转换方法如下:
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
Kotlin 中各数字类型所占位数如下:
类型 | 大小(bit) |
---|---|
Double | 64 |
Long | 64 |
Float | 32 |
Int | 32 |
Short | 16 |
Byte | 8 |
数值常量和 Java 中基本无区别,十进制:123,十六进制:0x1F。
主要是以下几种字面值常量:
- 十进制数值: 123
- 长整型要加大写 L : 123L
- 16 进制:0x0f
- 二进制:0b00001011
- 默认双精度浮点数 (Double) : 123.5 , 123.5e10
- 单精度浮点数 (Float) 要添加 f 或 F :123.5f
注意: Kotlin 不支持八进制(Java 支持,但很少使用)
2.Kotlin变量声明方式
变量的声明主要为 var 和 val 这两个,区别如下:
- var:定义可变变量
val:定义不可变常量
val a = 3
// 等价于
val a: Int = 3
// 等价于Java
final int a = 3;var b = 4
b = 5
println(b) // 5
// 等价于Java
int b = 4;
b = 5;
println(b)
上面的代码块中 val 表示此为只读类型,不可更改,相当于 Java 中在类型定义上加上 final 关键字。
var 则为可读可写,可以对定义为此类型的进行赋值。
如果注意的话,上面的变量的类型是定义在变量名后面的,这点可能刚开始的时候不太习惯,但记住熟悉后即可,如果类型可自动推断出来,则可以省略不写。包括后面函数的参数类型也是放在参数的后面并用 :
分割。
如果细心的你,可能发现上面的代码块中每行的末尾都没有 ;了,这一点正是 Kotlin 的特点。
强调: Kotlin 中不会在末尾写分号啦!!!!!
另外: 在写 Int 或者 Long 类型数据时,常常一写一长串,不便于识别,现在 Kotlin 支持在数字常量中可以添加 _ 了,便于阅读,不影响数据类型和值,例如电话号码可以这样写了。val phone : Long = 186_1234_5678
便于我们阅读。不得不说 Kotlin 语言的灵活性。
3.空安全
在 Kotlin 是空类型安全的,所以如果要给一个变量赋值为 null,则必须在其定义后面加上 ?
,否则编译器会报错。
var str : String ? = null
var size = str.length //此时会编译报错,提示可能为空
那么怎么获取呢,在 Kotlin 中提供两种方法来访问:
- 第一种为
?.
的访问形式,此种表示如果为空则不执行,非空再继续,则上面则可以写成这样val size = str?.length
- 第二种就是可能在执行前给变量赋值了,我们肯定它不为空,那么可以用 !!. 来获取,如下:
val size = str!!.length
,当然第二种你必须为运行时控制住做好心理准备。
4.延迟属性 lazy
延迟属性或者延初始化可以帮助我们在需要用到时在初始化,不需要时不初始化,帮助程序节省内存空间及启动速度。
在 Kotlin 中使用 lazy 关
键字来表示。直接看下面的例子:
// answer 不会立即初始化
val answer by lazy {
println("Calculating the answer...")
42
}
if (needAnswer()) { // 返回随机值
println("The answer is $answer.") // 此时计算出答案
}else {
// 这种情况 answer 永远不会进行初始化
println("Sometimes no answer is the answer...")
}
只有执行到上面 needAnswer() 为 true 时,answer 才会被初始化。 想想是不是我们写的很多初始化的代码,都可以用 lazy 来延迟初始化了。
注意: by lazy
所赋值的变量必须为 val 类型
5.字符串
字符串有两种表达方式,一种是可以带转义符的,另外一种是可以包含任意字符的。例如下面有转义的 val s = "hello world \n"
,但如果真正的字符串就是上面带有转义字符 \n 的,那么要怎么表示呢,Kotlin 中使用三引号 “”” 来表示,例如:val s = """hello world \n"""
这样 \n 就不会被转义为回车,而是原封原样的字符串了。 简单来说就是 “” 包裹的字符串会自动转换转义的内容,””” 包裹的字符串会原封不动的不变,不管里面有多少转义符包括换行等。
字符串还有了很好的模板特性,会极大的方便字符串拼接,操作等。下面就直接看例子:
val a = 1
var str : String = "this num value is $a"
a = 3
val s2 = "${str.replace("is", "was")}, but now is $a"
可以看到这极大的方便字符串的操作,使用$即可直接取到变量的值,如果在字符串中操作则使用表达式 ${} 直接对字符串进行操作。
6.== 与 === 的区别
在 Kotlin 中多了一种判断符 === 三个等号,这个特点呢就是判断两个对象是否指向同一个对象,也就是引用相等,而 == 则表示的数据的结构相等,也就是调用 equals 方法的返回值。例如:
var a : Int = 3
println(a===a) // true
var b : Int = a
var c : Int = a
println(b===c) // true
println(b==c) // true
这个相信大家比较容易理解。
7.控制流
控制流基本与 Java 中常用的保持一致,有 for,
while
,但 switch
在 Kotlin 中换为 when
,学过其他语言的应该都能很容易的掌握。
7.1 for循环
for 循环使用 in 关键字进行遍历,普通的如下:
val array = 1..100
for (value in array) {
print("value = $value")
}
1..100
表示连续的一个是闭区间,数学表达式:[1,100]。
对于之前 for 循环的步长使用 step
来表示
for (i in 1..100 step 2) {
print("i = $i")
}
step 2 类似 Java 中的 i += 2
为了表示开闭区间,可以使用 until
来替代..
表示。如下:1 until 100
表示 (1,100),这样则不包括 100 这个数字,如果从大到小,倒序的话将 ..
替换为 downTo
即可,步长依然使用 step
。
7.2 while循环
while
循环与 Java 一样,不在多说,以及 do while
。
7.3 when循环
when
的功能与 Java switch 功能类似,但是其便捷性不仅仅能 case
一些基本数据类型,它可以支持表达式,这样会更加的灵活便捷。下面看个例子吧:
fun describe(obj: Any): String =
when (obj) {
1,'1' -> "One"
"Hello","Good" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
看到上面的是不是很灵活?可以对不同的类型在同一个分支中进行判断,极大的提高了灵活性。每个 case 末尾也不用在写 Break 了。避免 Java 中忘记 Break 而导致异常情况。
8.集合
8.1 数组
在 Kotlin 中使用 Array 来表示数组,它本身定义了 set, get, size
等属性,可以使用 arrayOf
来创建数组,例如: var test = arrayof(1,2,3)
,数组中的数据类型可以是任何类型,但是使用时需要注意类型,访问可以用 get(index)
或者 [index]
来访问,
for (ar in array) {
print("array value = $ar")
}
for (i in array.indices) { // indices 返回下标
print("array value = $array[i]")
}
8.2 List
list 的创建也很简便,使用 listOf 创建,使用 val list = listOf(1,2,3,"string")
,当然遍历也提供了多种方式,如下:
for (it in list) {
print("list value = $it")
}
// 带下标,以及值的遍历方式
for ((index,value) in list.withIndex()) {
print("index = $index value = $value " )
}
8.3 Map
map 的创建 val map = mapOf("a" to 1, "b" to 2, "c" to 3)
,访问也是很简单,比 Java 中访问简单太多,方式如下:
for ((key, value) in map) {
print("key = $key value = $value")
}
看到上面常见集合的类型套路都是一样使用类型 Of()
来创建,访问遍历也是很方便。
9.函数
9.1 函数的定义
函数在 Kotlin 中使用 fun 来表示,函数参数与定义变量一样放在变量后面,参数的类型不可省略,返回值也是在放在参数括号后面,当没有返回值的时候使用 Unit 代替 Java 中的 void 关键字,当然 Unit 也是可以省略的。下面我们看几个例子:
fun sum(a: Int, b: Int): Int {
return a + b
}
// 等同于下面语句,简称函数式表达式
fun sum(a:Int, b:Int) = a + b
val sum = { x:Int ,y:Int -> x + y}
上面就是一个简单的函数,有参数又返回值。
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${ a + b}")
}
// 等同于下面
fun printSum(a: Int, b: Int) {
println("sum of $a and $b is ${ a + b}")
}
上面则为没有返回值,其可以将函数后面的 Unit 省略掉。
9.2 函数默认参数
在 Java 中我们如果对同一个方法名,但是有不同的参数个数,需要写多个方法出来,看起来很臃肿,对于少参数的来说,可能就是某个参数为固定或者默认值,那么在 Kotlin 中有了默认参数的表示方式。例如:
fun sum(a :Int , b : Int = 3) : Int {
return a +b
}
//调用 sum(1,2) // 代表 1 + 2
//调用 sum (2) // 代表2 + 3
9.3 函数具名参数
具名参数是对上面的一种特殊情况的考虑,比如我们将上面的代码改为如下:
fun sum(a :Int = 3, b : Int) : Int {
return a +b
}
//调用 sum (2) 此时对于此调用,编译器认为2 是为a赋值,而b没有赋值,无法编译通过。那么要调用则采用具名参数来指明参数。
// 改为 sum(b = 2) 这样既可指定将2赋值给b,则a使用默认的值。
9.4 扩展函数
在 Android 可能很常见的是有一个 Utils 包,专门放置一些常用的公共方法,比如 String、Toast、File 操作等等,然而现在 Kotlin 可以直接对系统类,或者自己写的类(通过拓展来分来模块),进行扩展。
fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {
Toast.makeText(this, message, duration).show()
}
//在Activity,Context实例中就可以直接调用了。
toast("我是Toast")
当然拓展不能复写系统已有的方法。只能是在类上添加方法。
还没有评论,来说两句吧...