既然选择学习了,那就学习最新的,学习最时髦的;同时也为了兼容 java ,我到时候都尽量把两种都写一写。
1. 通用语法
我就少记录相同的了,我说的相同是指跟 java,c,js 和 ts 做比较。
基本类型部分跟其他的差不多,写法跟 ts 相似。
var count1 = 10;
// 或者这样
var count2: Int = 10;
看 ts 的写法:
var a: number = 100;
大同小异。kotlin 的类型推断我觉得在 ide 中很好用,因为即便不写类型也有代码提示,非常棒,反观 ts ,如果不写类型,默认是 any ,所以你懂的。
2. 有意思的条件语句
下面从有意思的语法说起:
传统语言的三元运算符像下面这样:
// java
int a = 10;
int b = a > 10 ? 100 : 200;
几乎所有的语言都是这样,如果我们使用三元运算符做多个判断就变成下面这样了:
a > 10 ? (a > 5 ? (a > 2 ? 20 : 10) : 100) : 1000;
发现了没,可读性随着条件的数目而变得不堪,所以在这种情况下,我们就想到了使用 if-else 的方式:
if (a > 10) {
if (a > 5) {
if (a > 2) {
b = 20;
} else {
b = 10;
}
} else {
b = 100;
}
} else {
b = 1000;
}
好吧,发现仍然不可读,于是我们思考思考,也许可以这样,使用: if-elseif-else 的方式:
if (a <= 2) {
b = 10;
} else if (a <= 5) {
b = 100;
} else if (a <= 10) {
b = 20;
} else {
b = 1000;
}
这样感觉就好多了,只不过我们仍然做了重复的事情,那就是赋值,于是就在想能不能这样:
b = if (a <= 2) 10
else if (a <= 5) 100
else if (a <= 10) 20
else 1000
// 或更简单点
b = when {
a <= 2 -> 10
a <= 5 -> 100
a <= 10 -> 20
else -> 1000
}
想象就很棒对吧,结果如你所看到的, kotlin 已经做到了,我非常喜欢。 只不过原来的三元运算符没有了,感觉有点遗憾,因为我感觉在面对仅有一个判断的时候还是很好用的,我经常使用。
3. 万恶的 NullPointerException
下面再来看 NullPointerException 。先看两个例子:
// java
class JavaTest {
String name = null;
}
public class Main {
public static void main(String[] args) {
JavaTest test = null;
String result = test.name.toUpperCase();
System.out.println(result);
}
}
输入的结果:Exception in thread "main" java.lang.NullPointerException at Main.main(Main.java:8) 。
再来看 kotlin :
class Test {
var languageName: String? = null
}
fun main() {
val test: Test? = null;
print(test?.languageName?.toUpperCase())
}
输入 null 。
相对来说我还是比较喜欢 kotlin 的方式,可能是因为我也喜欢 ts 的原因吧。
曾几何时,我使用 java 做 android 开发,有一个噩梦,就是上面的空指针异常,说实话,那个时候本身我对 java 也是不熟悉的,只是能写,再加上我做的跟多线程相关,导致我当时真的非常难受,铺天盖地的空指针异常,后来我都怕了,只要有对象的地方我就会去捕获空指针的异常,想想都后怕。
4. 函数
4.1 跟以前差不多的函数
普通函数没有什么说的,跟 ts 差不多,如:
fun add(a: Int, b: Int): Int {
return a + b
}
// 调用
add(20, 30)
4.2 有默认值的函数
fun add(c: Int, a: Int = 10, b: Int): Int {
return a + b
}
// 调用
add(10, 20, 30)
add(10, b = 20)
有默认值的可以不传,没有的必须传。如果有没有默认值的在有默认值参数的后面,那么就需要指定参数名称的方式进行,就像 add(10, b = 20) 这样,由于 b 必须传,而又不想传 a ,那么就可以直接指定参数名直接进行传递。这种方式叫使用 具名参数 。
4.3 lambda 表达式
这个第一次是在 java 中编写的。 kotlin 中的:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
函数的参数默认是不可变的,不能在函数中进行修改,感觉这肯定是为了防止不小心修改了参数的值,而函数的其他地方去使用,这时值就不是我们想的那样了。下面实现排序的函数:
fun sort(arr: IntArray, sort: (Int, Int) -> Int) {
for (i in arr.indices) {
var k = i
// 找到最大或者最小的那个值
for (j in i + 1 until arr.size) { if (sort(arr[k], arr[j]) > 0) { k = j } }
// 如果找到这个值就交换
if (i != k) { arr[i] = arr[k].apply { arr[k] = arr[i] } }
}
}
下面就使用 lambda 来调用:
val arr = intArrayOf(1, 20, 3, 4, 5)
sort(arr) { a: Int, b: Int -> a - b }
arr.forEach { println(it) }
不知道为啥,还是喜欢 js 中的匿名函数 (a: number)=>number ,看来需要一段时间来适应。
4.4 单表达式函数
也就是一个函数如果只有一个表达式的话,可以像下面这样,其实我觉得如果只有一个的话,只要不要很长的那种表达式,完成可以不写函数,直接调用:
// 不需要返回
fun printHello(): Unit = print("吴敬悦")
// 需要返回
fun calcMul(a: Int, b: Int): Int = a * b
需要说明一下,没有任何返回值在 java 中是 void ,但是在 kotlin 中使用 Unit 即可。
如果一个函数不返回任何有用的值,它的返回类型是 Unit。
4.5 带有可变参数的函数
如果一个参数具备一个或多个,那么需要在参数前添加 vararg 关键词。
fun asList(vararg digits: Int):IntArray {
return intArrayOf(*digits)
}
// 像下面这样调用
asList(1, 2, 3, 4, 5)
fun add(vararg c: Int, a: Int): Int {
return c.reduce { m: Int, n: Int -> m + n } + a
}
add(1, 2, 3, 4, 5, a = 20)
4.6 高阶函数
高阶函数是将函数用作参数或返回值的函数。
上面我们编写 sort 函数中用到了。









网友评论