kotlin 基础知识

kotlin 基础知识

中文官方

kotlin官方sample

介绍

基础语法(一)

1
2
3
4
5
6
7
8
9
10
11
12
fun getGreeting(): String {
val words = mutableListOf<String>()
words.add("Hello,")
words.add("world!")
return words.joinToString(separator = " ")
}

fun main(args: Array<String>) {
println(getGreeting())
}
输出:
hello world

for 循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun testFor(){
val items = listOf("apple", "banana", "kiwifruit")
for (item in items) {
println(item)
}

for (index in items.indices){
print("index is $index value is ${items[index]} \n")
}
}
输出:
apple
banana
kiwifruit
index is 0 value is apple
index is 1 value is banana
index is 2 value is kiwifruit

while 循环

1
2
3
4
5
6
7
8
9
10
11
12
13
fun  testWhile(){
val items = listOf("apple", "banana", "kiwifruit")
var index = 0
while ( index < items.size){
println("items is ${items[index]}")
index++
}
}

结果:
items is apple
items is banana
items is kiwifruit

When 表达式 (java的switch)

1
2
3
4
5
6
7
8
9
fun testWhen( a : Int){
when(a){
0, 1 -> print("x == 0 or x == 1")
4 -> println("x == 4")
in 5..10 -> println("x in 5 ..10")
!in 100..200 -> println("x !in 100..200")
else -> print("otherwise")
}
}

使用区间(range)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
fun testRange(){
var i = 4
if (i in 1..10) { // 等同于 1 <= i && i <= 10
println(i)
}

for (i in 1..4) print(i)
println()
for (i in 4 downTo 1) print(i)
println()
for (i in 1..10 step 2) print(i)
println()
for (i in 1 until 10) {
// i in [1, 10) 排除了 10
print(i)
}
}

结果:
4
1234
4321
13579
123456789

Maps 遍历

1
2
3
4
5
6
7
8
fun testMap(){
var maps = mutableMapOf<String,String>();
maps.put("key1","value1")
maps.put("key2","value2")
for ((k, v) in maps) {
println("$k -> $v")
}
}

空安全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 空安全
*/
fun testNull(){
// 编译错误,编译不通过,s 不能为空,
// var s : String = "abc"
// s = null
// 便通过,s1 可以为空

// var s1 : String? = "abc"
// s1 = null
// // 还是编译不通过,s1为空
// print(s1.length)

// 安全调用,b?.length 返回Null ,不会出异常
// val a = "Kotlin"
// val b: String? = null
// println(b?.length)
// println(a?.length)

// !! 操作符 非空断言运算符 kotlin.KotlinNullPointerException
var b : String? = null
val l = b!!.length

var data = 3
//当data不为空的时候,执行语句块
data?.let{
println("data is not null")
}
}

Elvis 操作符

1
2
3
4
5
6
7
val l: Int = if (b != null) b.length else -1

// 应用 ?: 表达式之后
val l = b?.length ?: -1

如果 ?: 左侧表达式非空,elvis 操作符就返回其左侧表达式,否则返回右侧表达式。
请注意,当且仅当左侧为空时,才会对右侧表达式求值。

####高阶函数与 lambda 表达式

基本类型

1
2
3
4
5
6
7
Type	Bit width
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

###函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
函数的声明:
fun say(str: String): String {
return str
}

简写:fun say(str: String): String = str
在简化:fun say(str: String): str

函数的默认参数:
fun say(firstName: String = "Tao",
lastName: String = "Zhang"){
}

变参函数:

//在Java中,我们这么表示一个变长函数
public boolean hasEmpty(String... strArray){
for (String str : strArray){
if ("".equals(str) || str == null)
return true;
}
return false;
}

//在Kotlin中,使用关键字vararg来表示
fun hasEmpty(vararg strArray: String?): Boolean{
for (str in strArray){
if ("".equals(str) || str == null)
return true
}
return false
}

嵌套函数

Kotlin 的函数有一些非常有意思的特性,比如函数中再声明函数。
与内部类有些类似,内部函数可以直接访问外部函数的局部变量、常量,而外部函数同级的其他函数不能访问到内部函数。这种写法通常使用在 会在某些条件下触发递归的方法内或者是不希望外部其他函数访问到的函数,在一般情况下是不推荐使用嵌套函数的

1
2
3
4
5
6
7
8
9
10
11
fun function() {
val str = "hello!"

fun say(count: Int = 10) {
println(str)
if (count > 0) {
say(count - 1)
}
}
say()
}

构造函数

Kotlin 的构造函数可以写在类头中,跟在类名后面,如果有注解还需要加上关键字constructor。这种写法声明的构造函数,我们称之为主构造函数。例如下面我们为Person创建带一个String类型参数的构造函数。在构造函数中声明的参数,它们默认属于类的公有字段,可以直接使用,如果你不希望别的类访问到这个变量,可以用private修饰。
在主构造函数中不能有任何代码实现,如果有额外的代码需要在构造方法中执行,你需要放到init代码块中执行。同时,在本示例中由于需要更改 name 参数的值,我们将 val 改为 var,表明 name 参数是一个可改变的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
open class Person (private var name : String){

private var description = "";

init {
name = "zlz"
println("init $name")
}

constructor( name : String , des : String) : this(name) {
this.description = des
println("constructor $name")
}

fun sayHello(){
println("sayHello name is $name , description is $description")
}

var person = Person("hello","xiaoqiang")
person.sayHello()

结果:
init zlz
constructor hello
sayHello name is zlz , description is xiaoqiang

}

次级构造函数

一个类当然会有多个构造函数的可能,只有主构造函数可以写在类头中,其他的次级构造函数(Secondary Constructors)就需要写在类体中了。次级构造函数调用了主构造函数,完成 name 的赋值。由于次级构造函数不能直接将参数转换为字段,所以需要手动声明一个 description 字段,并为 description 字段赋值。

修饰符

1
2
3
4
5
6
open 修饰符
Kotlin 默认会为每个变量和方法添加 final 修饰符。这么做的目的是为了程序运行的性能,其实在 Java 程序中,你也应该尽可能为每个类添加final 为每个类加了final也就是说,在 Kotlin 中默认每个类都是不可被继承的。如果你确定这个类是会被继承的,那么你需要给这个类添加 open 修饰符。
internal 修饰符
Java 有三种访问修饰符,public/private/protected,还有一个默认的包级别访问权限没有修饰符。
在 Kotlin 中,默认的访问权限是 public,也就是说不加访问权限修饰符的就是 public 的。而多增加了一种访问修饰符叫 internal。它是模块级别的访问权限。
何为模块(module),我们称被一起编译的一系列 Kotlin 文件为一个模块。在 IDEA 中可以很明确的看到一个 module 就是一个模块,当跨 module 的时候就无法访问另一个moduleinternal 变量或方法

枚举类

Kotlin 与 Java 混编

Java 转换为 Kotlin

Intellij IDEA 会帮你一键转换,将 Java 代码转换成 Kotlin 代码(但是反过来就不行了)。在 Mac 上,系统默认的快捷键为control+shift+command+K,快捷键可以通过你的编译器 keymap 中修改:command+, -> 搜索keymap -> 右侧搜索kotlin,可以查看到Convert Java File to Kotlin File项。

在 Kotlin 中调用 Java 代码

1
2
3
4
5
6
7
8
9
10
11
fun invokeJava(source: List<Int>){
var calendar = Calendar.getInstance();
if (calendar.firstDayOfWeek == Calendar.SUNDAY) { // 调用 getFirstDayOfWeek()
calendar.firstDayOfWeek = Calendar.MONDAY // 调用ll setFirstDayOfWeek()
}
if (!calendar.isLenient) { // 调用 isLenient()
calendar.isLenient = true // 调用 setLenient()
}

}
Calendar.getInstance() 是Java中的类
返回 void 的方法

如果一个 Java 方法返回 void,那么从 Kotlin 调用时中返回 Unit。 万一有人使用其返回值,它将由 Kotlin 编译器在调用处赋值, 因为该值本身是预先知道的(是 Unit)

#####将 Kotlin 中是关键字的 Java 标识符进行转义
一些 Kotlin 关键字在 Java 中是有效标识符:in、 object、 is 等等。 如果一个 Java 库使用了 Kotlin 关键字作为方法,你仍然可以通过反引号(`)字符转义它来调用该方法:

1
2
3
4
5
6
7
8
9
// Java 代码中有个方法叫 is()
public void is(){
//...
}

// 转换为 Kotlin 代码需要加反引号转义
fun `is`() {
//...
}
static 方法

在 Kotlin 中没有 static关键字,那么如果在 Java 代码中想要通过类名调用一个 Kotlin 类的方法,你需要给这个方法加入@JvmStatic注解(这个注解只在 jvm 平台有用)
companion object表示外部类的一个伴生对象,你可以把他理解为外部类自动创建了一个对象作为自己的field

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
写法一
object StringUtils{
@JvmStatic fun isEmpty ( str : String) : Boolean{
return ""==str
}
}
写法二
class StringUtils {
companion object {
fun isEmpty(str: String): Boolean {
return "" == str
}
}
}

StringUtils.isEmpty("hello");
StringUtils.Companion.isEmpty("hello");

Java 中调用 Kotlin

####委托