Kotlin学习笔记(二):变量与函数

之前文章起名为Kotlin教程,后来想想可能不大合适,决定改为Kotlin学习笔记。上一篇文章发布后,有几个读者留言问在没有学Java的情况下,直接学Kotlin行不行?我认为是没有问题的。好了,上一篇文章已经简单了解Kotlin的一些特色,后面也用Kotlin写了一个最简单的HelloWorld,如果还不大清楚的朋友,可以先阅读上一篇文章:Kotlin学习笔记(一):走进Kotlin的世界

包名

Kotlin在包名声明和类型导入上和Java基本一样,风格如下:

1
2
3
4
package xxx.xxx.xxx //包名声明
import xxx.xxx.xxx //类型导入
...

和每个Java文件都会默认导入import java.lang.* 一样,Kotlin也会默认导入如下的包,并且根据运行在不同平台上,默认导入的包会有些许差异。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 每个Kotlin文件会默认导入下面的包
kotlin.*
kotlin.annotation.*
kotlin.collections.*
kotlin.comparisons.*
kotlin.io.*
kotlin.ranges.*
kotlin.sequences.*
kotlin.text.*
// JVM下的Kotlin还会导入
java.lang.*
kotlin.jvm.*
// JS下的Kotlin还会导入
kotlin.js.*

数值类型

Kotlin的数值类型包括Byte(1个字节)、Short(2个字节)、Int(4个字节)、Long(8个字节)、Float(4个字节)、Double(8个字节)。

字面常量

  • 十进制数:123
  • 长整型要加L:123L
  • 十六进制数:0x0f
  • 二进制数:0b00001011
  • Kotlin不支持八进制数
  • 双精度浮点数(Double):123.5 、 123.5e10
  • 单精度浮点数(Float)要加f或F:123.5f

Kotlin1.1版本开始,可以使用下划线来增强可读性

1
2
3
4
5
val oneMillion = 1_000_000
val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

布尔值

关键字Boolean,只有true和false两种取值,和Java一样可以使用&&||!进行与或非操作。

运算符

Kotlin支持标准的算数操作符,同时也支持下面各种位运算

  • shl(bits) – 有符号左移(signed shift left,相当于Java的<<)
  • shr(bits) – 有符号右移(signed shift right,相当于Java的>>)
  • ushr(bits) – 无符号右移(unsigned shift right,相当于Java的>>>)
  • and(bits) – 按位与(bitwise and,相当于Java的&)
  • or(bits) – 按位或(bitwise or,相当于Java的|)
  • xor(bits) – 按位异或(bitwise xor,相当于Java的^)
  • inv() – 按位取反(bitwise inversion,相当于Java的~)

以上这些位运算符只对Int和Long型有用。

1
2
3
var x = (1 shl 2) and 0x000FF000
var y = 0x000FF000
var z = y.inv() //z是y取反获得的

字符

关键字Char,和Java中char基本用法差别不大。

1
var useChar: Char = 'c'

数组

关键字Array,Kotlin中数组的使用和Java差别挺大,比如我要创建数组,就得使用arrayOf

1
2
3
//使用arrayOf简单创建数组
var students: Array<String> = arrayOf("Clock", "D_clock", "技术视界")
var studentNums = arrayOf(1, 2, 3)

使用arrayOfNulls可以创建一个指定长度,元素内容为空的数组

1
2
//创一个长度为10,元素内容皆为null的数组
var emptyArray = arrayOfNulls<String>(10)

Kotlin对一些基础类型定义数组会有拆装箱的开销,所以也可以使用自身封装好的一些API进行创建数组,以降低开销

1
2
//创建一个int数组,避免封箱装箱操作
var intArray = intArrayOf(1, 2, 3)

Kotlin数组还支持使用闭包进行初始化,就像下面这样

1
2
//使用闭包初始化一个Array<String>,数组内容为["0", "1", "4", "9", "16"]
var asc = Array(5, { i -> (i * i).toString() })

字符串

关键字String,用法和Java差别不大。

1
2
var useString: String = "I am a boy"
var firstChar: Char = useString[0] //相当于Java的String.charAt(0)

Kotlin的同样支持字符串模板,但是相比Java的String.format要简洁很多。比如:

1
2
3
var nickname: String = "D_clock爱吃葱花"
println("my nickname is $nickname")//输出昵称
println("nickname length: ${nickname.length}")//输出昵称的长度

定义变量

Kotlin的变量分为可变和不可变,和Java中是否对变量声明final一样,它定义一个变量的语法如下:

1
可变类型 变量名:数据类型
  • 可变类型分为var、val两种,分别代表可变、不可变;
  • 数据类型包括Kotlin内置的数据类型以及自定义类deng ;
  • 定义变量时需要明确数据类型;

对照Kotlin和Java给出一段简单的示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
/***Kotlin版代码***/
//定义可变变量
var id: Int = 1 //
var name: String = "D_clock爱吃葱花"
//定义不可变变量
val useVal: Int = 1000
/***Java版代码***/
int id = 1;
String name = "D_clock爱吃葱花";
final int useFinal = 1000;

Kotlin是支持类型推导,在定义变量时可以不显式声明类型,而通过赋值来确定变量类型。因此,定义变量的代码也可以写成下面这样

1
2
3
//类型推导
var tmpId = 1
var tmpName = "D_clock爱吃葱花"

定义函数

Kotlin定义一个函数的风格大致如下

1
2
3
4
访问控制符 fun 方法名(参数,参数,参数) : 返回值类型{
...
...
}
  • 访问控制符:与Java有点差异,Kotlin的访问范围从大到小分别是public、internal、protected、private,不声明默认是public;
  • 返回值类型:不需要返回类型的函数,后面的 : 返回值类型可以缺省(这里可以看到无论是变量还是方法,Kotlin都喜欢名字在前,类型在后);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***Kotlin版代码***/
//有返回参数的函数
fun getName(): String {
return "Kotlin"
}
//无返回参数的函数
fun displayName(name: String) {
println("name: $name")
}
/***Java版代码***/
public String getName() {
return "Java";
}
public void displayName(String name) {
System.out.println("name: " + name);
}

相比Java,Kotlin支持包级函数,即函数不依赖于类而存在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/***Kotlin版代码***/
package lesson1
/**
* Created by Clock on 2017/6/18.
*/
fun main(args: Array<String>) {
println("Kotlin")
}
/***Java版代码***/
package lesson1;
/**
* Created by Clock on 2017/6/18.
*/
public class Lesson1 {
public static void main(String[] args) {
System.out.println("Java");
}
}

对比上面的代码,Java创建一个方法前还需要先创建一个类。刚开始安装IntelliJ IDEA编写代码时,我还有个疑惑,为什么有创建Kotlin File/Class两个选择,到这里就明白了。

参数变长

Kotlin的参数变长非常简单,传递的参数使用关键字vararg标明即可

1
2
3
4
5
6
7
8
9
10
11
12
/***Kotlin版代码***/
//参数变长
fun displayActors(vararg name: String) {
println("actors: " + name);
}
/***Java版代码***/
public void displayActors(String... name) {
System.out.println("actors :" + name);
}

相比Java,变长参数在Kotlin代码中要常见很多。

静态变量和函数

Kotlin没有Java中的static概念,如果在Kotlin中需要像Java一样定义静态变量和函数可以使用companion object,companion object后可以加上自定义的object名,也可以省略。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***Kotlin版代码***/
class KotlinStatic {
companion object Test {
var kotlinInt: Int = 0
fun getInstance(): KotlinStatic {
return KotlinStatic()
}
}
}
/***Java版代码***/
public class Lesson1 {
public static int javaInt = 0;
public static Lesson1 getInstance() {
return new Lesson1();
}
}

这样在需要使用的地方就可以做如下调用了

1
2
3
4
5
6
7
8
9
10
11
12
13
package lesson0
import lesson1.KotlinStatic
/**
* Created by Clock on 2017/6/17.
*/
fun main(args: Array<String>) {
println("Hello, world!")
KotlinStatic.kotlinInt
KotlinStatic.getInstance()
}

虽然看起来companion object实现了类似Java中static一样的功能,但与Java不同的是,Kotlin在运行时是会创建一个companion object实例对象。在Kotlin中,如果真的想要实现和Java中的static变量或函数,官方更推荐使用包级别的变量或函数来实现。

If表达式(语句)

Kotlin中的If不同于Java,它是不仅能够作为一个判断语句,而且还是一个表达式,即执行If判断是有返回值的。

1
2
3
4
5
6
7
8
9
10
11
12
13
fun useIf() {
//使用If表达式判断a、b的大小
var a = 5
var b = 3
var result = if (a > b) {
println("a > b")
true //返回结果
} else {
println("a <= b")
false
}
println("result: $result")
}

If表达式里每个条件代码块中的最后一行执行语句即为返回值,相当于Java中的三元运算符:条件 ? 然后 : 否则,所以在把If当成表达式使用时必须有else分支,这样在逻辑上才能保证最终一定有返回值,否则会报语法错误。

When表达式(语句)

Kotlin中的When和If一样,既可以作为语句,也可以作为表达式,在作为语句时,它相当于Java中的switch。下面是对传入的参数input做一个判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fun useWhen(input: Int) {
var result = when (input) {
//判断input是否为1
1 -> println("input == 1")
//判断input是否为2
2 -> {
println("input == 2")
}
//input是否在10到20的范围内
in 10..20 -> println("input number in the range")
//input是否不在20到30的范围内
!in 20..30 -> println("input number outside the range")
else -> { //When作为表达式使用时,最后一定要以else
println("input: $input")
}
}
println("result: $result")
}

从上面的代码看,你会发现它比Java的switch灵活多了。这里只是使用When语句,如果要使用When表达式,则应该If表达式一样,最终一定要以else结尾。

For循环

for循环能够对任何提供迭代器(iterator)的对象进行遍历,语法格式如下:

1
2
3
4
for (item in collection){
//代码块
...
}

和Java有区别,但是也非常简单,Kotlin中的for更类似Java中的增强for循环。

1
2
3
4
5
6
7
8
9
10
fun useFor() {
val students: Array<String> = arrayOf("Clock", "D_clock", "技术视界")
for (student in students) {//输出学生名字
println("student: $student")
}
for ((index, student) in students.withIndex()) {//输出学生的下标和名字
println("the element at $index is $student")
}
}

While循环

Kotlin中的white(){}和do{}while()和Java差不多,这里不多做赘述。

1
2
3
4
5
6
7
8
9
10
11
12
fun useWhile() {
var counter = 10
while (counter > 0) {
counter--
println("counter: $counter")
}
do {
counter++
println("counter: $counter")
} while (counter < 10)
}

返回和跳转

Kotlin和Java一样有下面三种跳转表达式

  • continue:跳过这一次循环
  • break:终止包裹它的循环
  • return:从包裹它的函数或者匿名函数中返回

以上三种跳转都支持跳转到指定的标签处。标签的使用方式也简单,使用@在对应的循环或者匿名函数做标记即可,就像下方的示例代码一样

1
2
3
4
5
6
7
8
9
10
11
12
13
fun useJump() {
val numbers = arrayOf(1, 2, 3, 4, 5)
val numbers2 = arrayOf(1, 3, 5, 7, 9)
//设置testLab标签名
testLab@ for (num in numbers) {
println("num: $num")
for (num2 in numbers2) {
if (num == 3) {
break@testLab//直接中断标签指定的整个循环
}
}
}
}

总结

以上是本文整理的Kotlin一些基础语法笔记,如果有错误疏漏,欢迎指正。

本文为技术视界原创作品,转载请注明原文出处:http://blog.coderclock.com/2017/06/25/kotlin/kotlin-notes-1 ,欢迎关注我的微信公众号:技术视界

推荐文章