Kotlin for Java Developers 学习笔记

Kotlin for Java Developers 学习笔记

Coursera 课程 Kotlin for Java Developers(由 JetBrains 提供)的学习笔记

From Java to Kotlin

Java 和 Kotlin 代码可以相互转化

public class Person {
    private final String name;
    private final int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
}
class Person(val name: String, val age: Int)

Kotlin 被编译为 Java 字节码,所以从 Java 代码的层面看,这两者是一样的,都有一个 Constructor 和两个 Getter

也可以加上 data 修饰符,表示自动生成 equalshashCodetoString 这三个函数

data class Person(val name: String, val age: Int)

多个变量可以以 Pair 的形式赋值

val (description: String, color: Color) = Pair("hot", RED)

如果数据的类型在上下文中可以很明确地被推导出来,那么可以不用声明变量的类型

val (description: String, color: Color)
val (description, color)

多于 2 个 if … else … 时可以使用 when 关键字,类似于 switch,但又有细微区别

val (description, color) = when {
    degrees < 10 -> Pair("cold", BLUE)
    degrees < 25 -> Pair("mild", ORANGE)
    else -> Pair("hot", RED)
}

基本语法

Kotlin 的代码也是从 main 函数开始

package intro
fun main() {
    val name = "Kotlin"
    println("Hello, $name!")
}

从 Kotlin 1.3 开始

fun main(args: Array<String>)

可以只写

fun main()

变量、常量与字符串模板

字符串模板 $variable${args.getOrNull(0)}

“变量”分为 valvarval 是只读的

Kotlin 是静态类型的语言,每一个变量都会有自己的类型,但是我们可以在代码中省略基本类型,编译器会自动推断

var s = "abc" // var s: String = "abc"
var v = 123 // var v: Int = 123

我们不能给一个类型的变量赋值另一个类型的数据,例如:字符串常量赋值给一个 Int 类型的变量 string,这是一个编译时错误

var string = 1
string = "abc" // NOT ALLOWED是不允许的,我们不能把

val 不对数据做任何强加的限制,仍然可以改变其引用的数据,例如通过 list.add() 去修改一个被 val 修饰的列表,只要这个列表本身是允许被修改的

val list = mutableListOf("Java") // list.add() 可以往 List 中加东西
val list = listOf("Java") // list.add() 是不存在的

函数

fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}

如果只有一句话(function wilth expression body),可以写成

fun max(a: Int, b: Int) = if (a > b) a else b

void 类型的函数在 Kotlin 中会以 Unit 的形式返回

Kotlin 的函数可以定义在任何地方:顶层、类的成员、函数中定义另一个函数

调用顶层函数相当于 Java 中的 static 函数

// MyFile.kt
package intro
fun foo() = 0
//UsingFoo.java
package other;
import intro.MyFileKt;
public class UsingFoo {
    public static void main(String[] args) {
        MyFileKt.foo();
    }
}

为变量提供默认值,不再需要重载各种函数

fun displaySeparatpr(character: Char = '*', size: Int = 10) {
    repeat(size) {
        print(character)
    }
}

displaySeparator() // **********
displaySeparator(size = 5) // *****
displaySeparator(3, '5') // WON'T COMPILE
displaySeparator(size = 3, character = '5') // 555

分支

在 Kotlin 中,if 是表达式

val max = if (a > b) a else b

没有三元表达式

(a > b) ? a : b

注意与 Python 的区别

max = a if a > b else b

在 Kotlin 中,when 可以当作 switch 使用,不需要 break

switch (color) {
 case BLUE:
  System.out.println("cold")
  break;
 case ORANGE:
  System.out.println("mild")
  break;
 default:
  System.out.println("hot")
}
when (color) {
    BLUE -> println("cold")
    ORANGE -> println("mild")
    else -> println("hot")
}

可以使用任何类型,可以用来判断多个条件

fun response(input: String) = when (input) {
 "y", "yes" -> "Agree"
 "n", "no" -> "Sorry"
 else -> "Not Understand"
}

可以做类型检查

if (pet instanceof Cat) {
    ((Cat) pet).meow();
} else if (pet instanceof Dog) {
 Dog dog = (Dog) pet;
 dog.woof();
}
when (pet) {
    is Cat -> pet.meow()
    is Dog -> pet.woof()
}

可以不需要参数

fun updateWeather(degrees: Int) {
 val (desc, color) = when {
        degrees < 5 -> "cold" to BLUE
        degrees < 23 -> "mild" to ORANGE
        else -> "hot" to RED
 }
}

循环

val map = mapOf(1 to "one", 2 to "two", 3 to "three")
for ((key, value) in map) {
    println("$key = $value")
}
val list = listOf("a", "b", "c")
for ((index, element) in list.withIndex()) {
    println("$index: $element")
}
for (i in 1..9) // 1 2 3 4 5 6 7 8 9

for (i in 1 until 9) // 1 2 3 4 5 6 7 8
for (ch in "abc")
for (i in 9 downTo 1 step 2) // 9 7 5 3 1

拓展函数

fun String.lastChar() = get(length - 1)
val c: Char = "abc".lastChar()

也可以直接在 Java 中使用 Kotlin 中定义的拓展函数

import lastChar from ExtensionFunctions.kt;
char c = lastChar("abc");

常用的有 withIndexgetOrNulljoinToStringuntiltoeqtoInt 等等

val set = hashSetOf(1, 7, 53)
println(set.javaClass) // class java.util.HashSet
fun main(args: Array<String>) {
    println("Hello, ${args.getOrNull(0)}!")
}
val regex = """\d{2}\.\d{2}\.\d{4}""".toRegex()
regex.matches("15.02.2016") // true
regex.matches("15.02.16") // false

特别的,untilto 这种,本身是需要通过 .() 调用的

1.until(10)
"Answer".to(42)

但是因为原型声明的时候允许 infix

infix fun Int.until(to: Int) = IntRange
infix fun <A, B> A.to(that: B) = pair(this, that)

所以可以省略 .()

1 until 10
"Answer" to 42

成员函数比拓展函数的优先级高,例如下例会输出 1,并得到一个警告,说 entension is shadowed by a member

class A {
    fun foo() = 1
}

fun A.foo() = 2 // Warning: Extension is shadowed by a member

A().foo() // 1

但是我们可以重载一个拓展函数

class A {
    fun foo() = "member"
}

fun A.foo(i: Int) = "extension($i)"

A().foo(2) // extension(2)

标准库

Kotlin 的标准库包括 Java 标准库和一些常用的拓展函数

没有所谓的 Kotlin SDK,只有 Java 的 JDK 和一些 extensions

Nullability

现代的编程语言应该把 Null Pointer Exception 变成编译时错误,而不是运行时错误

val s1: String = "always not null" // 不可以 = null
val s2: String? = null // 或者 = "a string"

对于一个可能为 null 的变量,我们应该始终用 if 语句检查

if (s != null) {
    s.length
}

在 Kotlin 中。可以使用 ? 来简化访问,如果对象为 null,则运行结果为 null,返回类型是 nullable 的基本类型

val length: Int? = s?.length

如果只想要基本类型,可以使用 elvis 运算符( elvis 来自 Groove)

val length: Int = s?.length ?: 0

可以使用 !! 强制抛出 NPE

elvis 的优先级比加减法低

val x: Int? = 1
val y: Int = 2
val z1 = x ?: 0 + y // 1
val z2 = x ?: (0 + y) // 1
val z3 = (x ?: 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凝神长老

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值