Kotlin学习(一)基础、语法、NULL机制、类型检测与自动类型转换
kotlin学习是通过对 Runoob 网所做的更容易理解的方式
Kotlin学习均以对照Java的实现方式为基准,便于使用Java的小伙伴转至Kotlin更容易理解
声明:
写东西难免出错,若本片博客出现任何错误的讲解欢迎下方留言纠正,谢谢
Kotlin不需要以 ; 结尾每一行代码
定义函数(方法)
关键字fun,书写格式为—>参数 : 类型
fun sum(a: Int,b: Int): Int{
return a + b
}
表达式作为函数体,返回类型自动判断
fun sum(a: Int,b: Int) = a + b
//注意:public方法必须明确写明返回类型
public fun sum(a: Int,b: Int): Int = a + b
无返回值类型函数(类似Java中void)
fun printSum(a: Int,b: Int): Unit{
print(a + b)
}
//注意:如果返回是Unit类型,可省略Unit关键字(public也是如此)
public fun printSum(a: Int,b: Int){
print(a + b)
}
函数的参数为可变长的
fun vars(vararg v: Int){
for(vt in v){
print(vt)
}
}
//测试
fun main(args: Array<String>){
vars(1,2,3,4,5)//输出12345
}
lambda(匿名函数)
//测试
fun main(args: Array<String>){
val sumLambda: (Int,Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2))//输出结果为:3
}
常量与变量(对应Java:final、变量)
变量:var关键字
var <标识符> : <类型> = <初始化值>
var study : String = "蓝瘦"
常量:val关键字(只能赋值一次的东西,类似Java的final)
val <标识符> : <类型> = <初始化值>
val study : String = "香菇"
常量/变量均可没初始化值,但必须在引用前初始化一下
编译器支持自动类型判断, 即声明时可不指定类型,由编译器判断
val a: Int = 1
val b = 1//系统自动判断类型为Int
val c : Int//如果不直接初始化就必须声明类型为Int
c = 1//引用时进行初始化
注释
单行、多行注释如下
// 这是一个单行注释
/* 这是一个多行的
块注释。 */
字符串模板
$ 表示一个变量名/变量值
$varName 表示varName这个变量的值
${varName.fun()} 表示varName变量的方法的返回值//变量还有方法?别担心,后面会讲到。
var a = 1
val s1 = "a is $a"
a = 2
val s2 = "${s1.replace("is", "was")}, but now is $a"
print(s2)
//输出:a was 1,but now is 2
//看不懂的小伙伴注意var和val再仔细看一下,其中花括号中代表替换掉s1也就是a is 1中的is为was
NULL检查机制
kotlin的空安全设计对于那些声明可为空的参数,在使用时要先进行空判断处理,两种方式
1.字段后加 !! 像Java一样抛出空异常
2.字段后加 ? 可不做处理,要么返回值为 null,要么通过 ?: 来做空判断处理(看不懂看下面)
//类型后加?表示age可为空
var age: String? = "23"
//var age: String? = null(可为空的形式)
//抛出空指针异常,其实 !! 简单说就是不管值是不是null都继续执行下去,如果说值是null还执行下去了,那么肯定就是空指针异常
val ages = age!!.toInt()
//不做处理返回 null,其实就是当age不为null时才会执行到toInt
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1
当一个引用可能为 null 时, 类型也必须明确地标记为可为 null。
如下当 str 中字符串的内容不是一个整数时, 返回 null:
fun parseInt(str: String): Int? {
// ...
}
以下演示如何使用一个返回值可为 null 的函数
fun main(args: Array<String>) {
if (args.size < 2) {
print("Two integers expected")
return
}
val x = parseInt(args[0])
val y = parseInt(args[1])
// 直接使用 `x * y` 会导致错误, 因为它们可能为 null.
if (x != null && y != null) {
// 在进行过 null 值检查之后, x 和 y 的类型会被自动转换为非 null 变量
print(x * y)
}
}
类型检测及自动类型转换
通过 is 运算符检测一个表达式是否为某类型的一个实例(类似Java中的instanceof关键字)
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 做过类型判断后,obj会被系统自动转换为String类型
return obj.length
}
//在这里还有一种方法,与Java中instanceof不同,使用 !is
// if (obj !is String){
// // XXX
// }
// 这里的obj仍然是Any类型的引用
return null
}
或者
fun getStringLength(obj: Any): Int? {
if (obj !is String)
return null
// 在这个分支中, `obj` 的类型会被自动转换为 `String`
return obj.length
}
甚至还可以
fun getStringLength(obj: Any): Int? {
// 在 `&&` 运算符的右侧, `obj` 的类型会被自动转换为 `String`
if (obj is String && obj.length > 0)
return obj.length
return null
}
区间(通俗易懂)
先看以下比较官方的说法:
区间表达式由具有操作符形式 ..
的 rangeTo 函数辅以 in 和 !in 形成
区间是为任何可比较类型定义的,但对于整形原生类型,它有一个优化的实现。
通俗些的往下看代码 ↓ :
for (i in 1..4) print(i) // 输出结果为:“1234”
for (i in 4..1) print(i) // 什么都不输出
if (i in 1..10) { // 等同于 1 <= i && i <= 10
println(i)
}//输出结果为:“12345678910”
// 使用 step 指定步长
//其实也就是说输出1的时候跳两步(1-->2-->3)便跳到了3到3的时候跳两步便会跳出4就没什么可输出了
for (i in 1..4 step 2) print(i) // 输出“13”
for(i in 2..10 step 3) print(i)//输出结果为“258”
//这里就是从4到1的意思(downTo字面意思就是向下)
//这里每输出一次跳2次结果也就是4和2了
for (i in 4 downTo 1 step 2) print(i) // 输出“42”
// 使用 until 函数排除结束元素
for (i in 1 until 10) { // i in [1, 10) 排除了 10
println(i)
}//执行结果为:"123456789"