Kotlin学习笔记

47次阅读

共计 4269 个字符,预计需要花费 11 分钟才能阅读完成。

1 概述

这篇文章首先会介绍 Kotlin 的特点,接着介绍 Kotlin 与 Java 的语法比较。

2 Kotlin 特点

  • 一门现代化的编程语言
  • 可开发跨平台应用,web,Socket,安卓,js,NativeApp 等
  • 静态编程语言,性能基本与原声 Java 相当
  • 100% 兼容 Java(说是兼容但实际上有些坑,可以戳这里看看)
  • 简洁:跟 Java 相比真的是简洁很多,语法糖特别舒服
  • 安全:彻底解决写 Java 基本上都会遇到的著名的 NullPointerException 问题,结合编译器可以在编译截断发现几乎所有可能存在 NPE 问题的代码
  • 互操作性:基于 JVM,可以直接拿现有的 Java 库用
  • 工具友好:和 JetBrains 的 IDE 结合简直舒服得不要不要的
  • 支持函数式编程:比如 Lambda 表达式
  • 支持协程:协程像是非常轻量级的县城,协程将复杂性放入库来简化异步编程,逻辑可以在协程中顺序表达,底层库负责解决异步性,很重要的一点是协程挂起不会阻塞其他线程。官方一个 demo 是开启 10w 个协程:

  • 支持扩展函数:类似 C#,能够扩展一个类的新功能而无需继承类或者使用装饰者这样的设计模式,Kotlin 支持扩展函数和扩展属性
  • 泛型:当然 Java 也支持泛型,但是 Kotlin 比 Java 支持得更好
  • 不依赖 XML

下面进入 Kotlin 的语法部分。

3 基本语法

  • ; 结尾
  • println()代替System.out.println();
  • 输出语句中使用 $ 变量名 代替 Java 中的 + 变量名,比如println("age:$age") 而不是System.out.println("age:"+age)
  • 三引号(三个双引号连在一起)中的字符串不会进行转义

4 变量与常量

  • var声明变量
  • val声明常量
  • 可以在 var/val 后面加上类型,比如val a:Int


如上图提示 val 不能被赋值,提示改为 varval 类似与 Java 中的 final,虽然val 引用自身不可变,但是指向的对象是可以改变的。

val只能进行唯一一次初始化,如果编译器能确保只有唯一一条初始化语句被执行,可以根据条件进行不同的初始化操作:

val a:Int
if (4>3)
{a = 9}
else
{a = 10}

5 表达式和语句

Java 中所有的控制结构都是语句,在 Kotlin 中除了三大循环(whilefordo while)外,大多数控制结构都是表达式。比如 if 是表达式而不是语句。也就是说,if有值而不像 Java 里面一样没有值(语句)。
例子:

var a = if (3>2) 3 else 2
fun main()
{var a = max(4,9)
}

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

6 枚举

使用 enum class 而不是 Java 中的enum

fun main()
{
    val months = Months.May
    println(months.days)
}

enum class Months(val days:Int)
{May(31),
    Jun(30)
}

7 when

when相当于 Java 中的switch

fun main()
{
    val months = Months.May
    when(months)
    {Months.May -> print("May")
        Months.Jun -> print("June")
    }
}

enum class Months(val days:Int)
{May(31),
    Jun(30),;
}

使用 -> 进行了简化。

8 循环

8.1 while 与 do while

与 Java 一样。

8.2 for

使用 .. 表示区间,在 i 前面没有类型:

for (i in 1..100)
    print(i)

注意区间是两边都包含的,也就是 1..100 表示 i 从 1 循环到 100。

使用下标迭代:

val arr = arrayListOf("1111","2222","333")
for ((i,e) in arr.withIndex())
    println("$i = $e")

输出:

0 = 1111
1 = 2222
2 = 333

9 类

9.1 构造方法

class Person(val name:String)

不需要像 Java 一样this.xxx=xxx

9.2 getter/setter

因为 val 代表常量,而 var 代表变量,setter 是用于改变值的,因此,使用 var 声明的属性具有 getter 与 setter,使用 val 声明的属性只有 getter。
Kotlin 没有提供直接操纵 getter 与 setter 的方式,通过使用 . 属性名 进行修改属性或者获取属性:

class Person
{var name = ""val id =""}
var person = Person()
person.name="111"
person.id="222" // 编译不通过,id 为 val 不可变

9.3 自定义 getter/setter

在相应的属性后面加上 get/set 即可自定义 getter/setter:

class Person
{
    var name=""
    get()
    {return "name"+field}
    var id=""
    set(id)
    {field = id}
}

get/set 中使用 field 表示字段,比如在上面例子中的 get 中,field表示 name,而在下面的set 中,field表示自己的 id= 后面是参数的id

10 异常

10.1 抛出异常

直接throw,无需new

val age = 300
if(age !in 1..100)
    throw IllegalArgumentException("Out of range:$age")

10.2 try/catch

try 
{throw Exception("exception")
}
catch (e:Exception)
{e.printStackTrace()
}

10.3 受检异常与不受检异常

Java 中的异常有两类:

  • Unchecked Exception:不受检异常,可以不进行 try/catch 处理,包括 Runtime Exception 及其子类
  • Checked Exception:受检异常,必须进行 try/catch 处理或者声明需要抛出,不属于不受检异常的异常都属于受检异常

Kotlin 不区分两者,也就是对于 Java 的受检异常可以不处理,比如:

fun main()
{throw IllegalArgumentException("333")
}

可通过编译,而 Java 中的

public class Test
{public static void main(String []args)
    {throw new Exception("111");
    }
}

则无法通过编译。

11 集合类

val arrayList = ArrayList<Int>()
arrayList.add(3)
arrayList.add(9)
arrayList.forEach {t-> println(t) }

val hashSet = hashSetOf<String>()
hashSet.add("2222")
hashSet.add("99999")
hashSet.forEach{t-> println(t)}

val list = listOf(3,5,5)
list.forEach{t-> println(t)}

val map = mapOf("a" to 1,"b" to 2)
map.forEach{(k,v)-> println("$k to $v")}

可以直接使用集合类或者 xxxOf 创建,遍历使用 forEach 与 Lambda,Kotlin 风格的 Lambda 使用{}

12 函数

12.1 基本语法

fun printStr(str:String)
{println(str)
}

fun add(a:Int):Int
{return a+3}
  • fun声明函数
  • 形参类型在形参名称后
  • 返回类型放在最后,前面需要带
  • 函数不强制放在类中

12.2 默认参数

Java 里面没有默认参数,实现类似功能需要重载去解决,而 Kotlin 的函数可以具有默认参数:

fun main()
{println(add())
    println(add(1))
    println(add(1,2))
}
fun add(a:Int = 3,b:Int = 4):Int = a+b

可以省略的只有在末尾的参数,也就是默认参数从末尾开始确定默认值。

12.3 命名参数

类似 Python,调用函数时使用形参名称与值的方式调用而不是仅仅通过值调用,同时可以结合默认参数省略部分值。

fun main()
{println(add(b=1))
    println(add(b=5,a=9))
}

fun add(a:Int = 3,b:Int = 4):Int = a+b

12.4 可变参数

使用vararg

fun main()
{println(add(1,2,3,4))
}

fun add(vararg a:Int):Int = a.sum()

13 顶层函数与顶层属性

13.1 顶层函数

Kotlin 中可以将函数放在代码文件的顶层,不用附属于任何类,但仍然是包内作用域,包外需要import,作用类似 Java 中的静态函数。

fun add(vararg a:Int):Int = a.sum()
fun main()
{println(add(1,2,3,4))
}

Java 中调用顶层函数时可以使用默认的 Kotlin 文件名作为默认包去调用,也可以使用 @file:JvmName 修改调用的包名,比如上面的文件名为Test.kt,则 Java 中调用的代码如下:

TestKt.add()

使用注解后:

@file:JvmName("Test")
fun add(vararg a:Int):Int = a.sum
fun main()
{println(add(1,2,3,4))
}

Java 调用方式改变如下:

Test.add()

13.2 顶层属性

与 Java 中的静态属性类似,有点像全局变量或全局常量,可以使用 varvalconst val 修饰:

var a = 0
val b = 0
const val c = 0

fun main()
{println(++a)
    println("$b\n$c")
    test()}

fun test()
{println("$a\n$b\n$c")
}

valconst val 的主要区别是:

  • val实质上相当与 Java 中的private final static
  • const val实质上相当于 Java 中的public final static
  • const相当于 @JvmField,也就是说const val a = 0@JvmField val a = 0等价:

14 参考

1、Kotlin 语言的特点和优劣势
2、Java 受检异常与不受检异常
3、Kotlin 中的 getter 与 setter
4、Kotlin 与 Java 的异同
5、Kotlin 之 const val 与 val

正文完
 0