Kotlin基础-语法
2011年JetBrains发布了Kotlin第一个版本; 2016年Kotlin发布了1.0正式版; 2017年Google宣布Kotlin成为Android一级开发语言.
基础知识
变量(varaibale)
val(value)用来声明一个不可变的变量, 对应Java中的Final. var(variable)用来声明一个可变的变量, 对应Java中的非Final.
// 完整的变量声明例子
val a: Int = 10
// Kotlin具有类型推导机制, 可以简化
val a = 10
Kotlin取消了Java的基本数据类型, 全部使用对象数据类型.
函数(function)
Java中多数称为方法(method). 声明方法需要fun关键字.
// 函数的创建语法.
fun 函数名称(参数1: 参数类型, 参数2: 参数类型): 返回值 {
return 返回值
}
// 示例 完整版
fun largerNumber(num1: Int, num2: Int): Int {
return max(num1, num2)
}
// Kotlin语法糖
// 当函数体只有一行代码时, 可以省略函数体{}, 将唯一一行代码
// 定义到函数声明的尾部, 并用=连接
fun largerNumber(num1: Int, num2: Int) : Int = max(num2, num1)
// 由于推导机制, 返回值声明可以省略.
fun largerNumber(num1: Int, num2: Int) = max(num2, num1)
// 函数支持默认值, 上面函数可以添加默认
fun largerNumber(num1: Int = 1, num2: Int = 2) = max(num2, num1)
逻辑控制语句
if条件语句
Kotlin的条件语句有两种: if, when
if语句和Java中的if几乎一模一样. 但Kotlin的if支持返回值, 就是每个条件的最后一行代码作为返回值.
when语句类似Java中的switch. 但不仅局限与Java的只能整型, 短整型,字符串
// when语法结构
when(变量){
匹配值 -> {执行逻辑}
匹配值 -> {执行逻辑}
}
// 示例
when(name){
"张三" -> {"20岁"}
"李四" -> {"21岁"}
"王五" -> {"22岁"}
}
// 简化, 由于和if一样, 函数体最后一句最为返回值, 并且函数体只有一行代码
// 可以省略{}
when(name){
"张三" -> "20岁"
"李四" -> "21岁"
"王五" -> "22岁"
}
循环语句
- while 与Java没有区别
- for 舍弃了Java中的for-i循环, 对Java中的for-each进行增强, 并变成了for-in循环
区间概念: 正是由于没有了for-i的变量控制条件,才出现了区间概念
// 创建一个0到100的区间
var range = 0..100
// 以上代码意思是. 一个0到100的区间, 并且两端都是闭区间, 也就是包含0和100.等价于数学中的
// [0,100]
// for-in 升序
for (i in 1..100){
println(i)
}
// 每次循环自增2
for (i in 1..100 step){
println(i)
}
类和对象
- Class 类, 同Java
- File 通常用于编写Kotlin的顶层函数和扩展函数
- Interface 接口, 同Java
- Enum class 枚举类
- Object 数据类
// 创建一个class类
class Person{
}
// 获取Person示例, 不需要new
var person = Person()
继承与构造函数
在Kotlin中任何一个非抽象类默认都是不可被继承的, 相当于Java中的String类添加了final关键字一样. 就如Effective java中提到的, 如果一个类不是为了专门继承而设计的, 就应该主动加上final. 而Kotlin把默认实现修改到final模式
那么如果要想一个类被继承, 使用open来修饰类.
open class Person{}
// Kotiln中使用 : 来代替Java中的extends
class Student : Person(){}
Kotlin中有两种构造函数: 主构造函数, 次构造函数
一个类只能有一个主构造函数, 但是可以很多个次构造函数. 一个类默认有一个不带参的主构造函数 一个类如果仅有一个次构造函数, 那么此类是没有主构造函数
// 主构造函数
// 每个类默认有一个不带参数的主构造函数
// 主构造函数特点是没有函数体, 只需在类名后显式的指明参数即可
// 如果需要编写构造逻辑, 使用Kotlin提供的init结构体
open class Person(age: Int, name:String){
init {
// 构造逻辑
}
}
// 次构造函数
// 当一个类既有主构造也有次构造, 那么所有的次构造都要调用主构造函数.
open class Person(age: Int, name: String) {
constructor() : this(11, "") {
}
constructor(age: Int, name: String, sex: Int) : this(age, name) {
}
}
接口
同样使用**:**来实现接口继承, 并且被继承的类不需要追加括号, 因为接口没有构造函数.
允许对接口中定义的函数进行默认是实现. 这一特性在Java JDK1.8之后也同样支持.
函数可见性修饰符
修饰符 | Java | Kotlin |
---|---|---|
Public | 所有类可见 | 所有类可见(默认) |
private | 当前类可见 | 当前类可见 |
protected | 本类,子类,同一包路径可见 | 当前类,子类可见 |
default | 同一包路径下的可见 | 无 |
internal | 无 | 同一模块中的类可见 |
数据类型与单例类
// 数据类实现 data关键字
// 不再像Java一样需要实现equals(), hashCode(), toString()等方法
data class schoolRool(val name:String, val id:Int)
// 单例类 object关键字
object Singleton{
}
集合
使用内置函数listOf简化初始化集合的写法
val list = listOf("张三", "李四", "王五")
遍历集合
for(person in list){....}
listOf() 函数创建的是不可变集合, 即只读不能修改删除. mutableListOf() 函数与之对应, 可变集合.
setOf() mutableSetOf()
Map
Kotlin提供了一中类似数组下标的语法结构提供读写.
val map = mutableMapOf("张三" to 1, "李四" to 2)
map["王五"] = 3 // 赋值
val age = map["李四"] // 取值
常用的一些函数式API
// 遍历集合元素, 并在函数体进行转换
list.map{ it.toUpperCase }
// 过滤集合, 进行筛选
list.filter{ it.lenght >= 5}
// 判断集合中是否至少存在一个元素满足条件
list.any { it.length >= 5 }
// 判断集合所有元素是否满足条件
list.all { it.length >= 5 }
Lambda
就是一小段可以作为参数传递的代码.
语法结构 {参数名1: 参数类型, 参数名2: 参数类型 -> 函数体}
推导简化过程
// 原始
val list = listOf("apple", "pear", "banana")
val lambda = { name: String -> name.length } // lambda语句, 最后为单句省略了花括号
val maxLength = list.maxOf (lambda)
// 不需要定义lambda变量, 直接传入
val maxLength = list.maxOf({ name: String -> name.length })
// 当Lambda参数是函数的最后一个参数时,可以移到函数括号外面
val maxLength = list.maxOf(){ name: String -> name.length }
// 当Lambda参数是函数的唯一参数时, 可以去掉函数的括号
val maxLength = list.maxOf{ name: String -> name.length }
// 由于推导机制, Lambda的参数类型声明可以去掉
val maxLength = list.maxOf{ name -> name.length }
// 当Lambda表达式只有一个参数时, 不必声明参数, 使用it关键字代替
val maxLength = list.maxOf{ it.length }
空指针
Kotlin默认所有的参数和变量都不可为空, 也就是说Kotlin将空指针异常的检查提前到了编译时期.
如果一个变量可空, 使用"?“关键字id Int?
判空辅助工具
person?.eat()
如果person为空就不调用eat()函数.
id?.lenght ?: 0
如果?:前为空就返回0, 否则不处理 ? : 逻辑
!! 非空断言
字符串内嵌表达式
"hi, ${person.name} "
当表达式中仅有一个变量的时候, 可以将两边的大括号省略.
关键字
- is 相当于Java中的instanceof, 判断对象类型.
- == 判断字符串或对象是否相等. 不再需要equals()专门判断字符串
- .. 区间声明(升序), 两端都是闭区间, 也就是两端数字都包含, 等价于数学中*[0,100]*
- until 区间声明(升序), 左闭右开区间, 包头不包尾,等价数学*[0,100)*
- downTo 区间声明(降序), 两端都是闭区间, 包头包尾, 等价数学*[100,0]*
- step 配合区间使用, 常规下区间是i++, i–,效果. 使用step 2, 实现循环中条件i=i+2的循环效果
- class 声明类
- open 修改类为可以被继承
- : 类的继承关系指向
- constructor 次构造函数声明
- data 数据类型声明.
- object 单例类声明
- ?. 判空辅助工具 不空就调用
- ?: 判空辅助工具 不空就返回
- !! 非空断言