写在前面
kotlin 为啥用fun声明方法?
JetBrains : We use “fun” because we like it - and yes, we do know what the word means in English.
需要注意的式Kotlin是基于JVM的语言,而不是基于Java的语言,他们都可以翻译成Class字节码。
kotlin
1.变量和标识符
- val 只读,相当于Java中的final修饰变量
- var可写
val pi = 3.14
pi = 3 // error val 初始化之后不能修改内容
另外Kotlin支持类型推断
var pi : Int = 3.14 // 完整写法
var pi = 3.14 // 根据初始化推断出变量的类型
2. 关键字和修饰符
修饰符按照修饰的内容可分为:类修饰符,成员修饰符,访问权限修饰符,协变逆变修饰符,函数修饰符等
类修饰符
类修饰符 | 说明 |
---|---|
abstract | 抽象类 |
final | 不可继承的final类 |
enum | 枚举类 |
open | 可继承open类 |
annotation | 注解类 |
sealed | 密封类 |
data | 数据类 |
成员修饰符
成员修饰符 | 说明 |
---|---|
override | 重写函数/方法 |
open | 声明函数可以被重写 |
final | 声明函数不可重写 |
abstract | 声明函数为抽象函数 |
lateinit | 延迟初始化 |
访问权限修饰符
访问权限修饰符 | 说明 |
---|---|
private | 私有,当前类访问 |
protected | 当前类,派生类访问 |
public | 默认值,对外可访问 |
internal | 模块类可访问 |
协变逆变修饰符
协变逆变修饰符 | 说明 |
---|---|
in | out T 相当于 ? extends T |
out | in T 相当于 ? super T |
函数修饰符
函数修饰符 | 说明 |
---|---|
tailrec | 尾递归 |
operator | 运算符重载 |
infix | 中缀函数 |
inline | 内联函数 |
external | 外部函数 |
suspend | 挂起协程函数 |
属性修饰符
属性修饰符 | 说明 |
---|---|
const | 常量修饰符 |
vararg | 变长参数 |
noinline | |
crossinline |
具体化类型修饰符
具体化类型修饰符 | 说明 |
---|---|
reified | 具体化类型参数 |
特殊语义关键字
关键字 | 说明 |
---|---|
is | 类型判断 |
object | 单例类声明 |
when | 条件判断,相当于witch |
by | 委托类或属性 |
init | 初始化代码块 |
get/set | get/set函数 |
*省去一些Java中出现的操作符
3. 流程控制语句
3.1 分支语句
-
if : if语句可以有返回值
fun max(a:Int , b:Int) : Int{ val max = if(a>b){ println("Max is a") a }else{ println("Max is b") b } return max }
-
when :相当于switch-case
fun casesWhen(obj : Any?){ when(obj){ 0,1,2,3,4,5,6,7,8,9 -> println("数字") "hello" -> println("字符串Hello") is char -> println("char 数据类型") else -> println("其他类型") // 相当于default } } // 上面每个case都相当于枚举 // case 还可以使用 in/!in 判断是否在区间 when(x){ in 1..10 -> println("x is in range 1 to 10") ! in 1..10 -> println("x is not in range 1 to 10") else -> println("kotlin 666") }
// 计算n!阶乘 fun fact(i: Int): Int { return when (i) { 0, 1 -> 1; else -> i * fact(i - 1) } }
3.2 循环结构
for 循环
// for in 循环
for(i in arr){
println(i)
}
// 索引循环
for(i in array.indices){
println(array[i])
}
// index-value 循环
for((index,value) in array.withIndex()){
println("元素$value的下标是$index")
}
// ranges 表达式循环
for(i in 1..10){
println(i)
}
{1..10}.forEach(print(it))
do-while/while循环
和java使用方法一样
3.3 跳转语句
return
return
= :
fun max(a : Int, b: Int) = if(a>b) a else b
' = '作为函数返回值匿名函数
val sum = fun(a:Int , b : Int) = a+b
-
Lambda表达式:
val sumf = fun(a: Int, b Int) = {a+b}
,调用lambda表达式返回的是一个函数`val sumf = fun(a:Int, b:Int) = {a+b} sumf(1,1) // 返回的是一个函数() - > Kotlin.Int sumf(1,1).invoke() // 调用这个函数 sumf(1,1)() // 和invoke效果一样
return在匿名函数和lambda表达式中作用不同
val intArray = intArrayOf(1,2,3,4,5)
intArray.forEach{
if(it == 3) return
println(it)
}
// 1,2
// 从lambda中return,lambda结束
intArray.forEach(fun(a:Int){
if(a == 3) return;
println(a)
})
// 1 2 4 5
// 从函数中return,函数执行结束
标签
val intArray = intArrayOf(1,2,3,4,5)
// 显式标签
intArray.forEach here@{
if(it == 3) return @here
println(it)
}
//隐式标签
intArray.forEach{
if(it == 3) return @forEach
println(it)
}
throw
val ex: Nothing = throw Exception("YYYYY") // 返回的类型式Nothing,不能作为函数的参数
4.运算符重载
和C++ 中比较类似,需要区别的式C++中重载'+/-/*/等'就是 operator后面加对应的符号就行了。但是kotlin中需要写对应的操作符
data class Point(val x: Int, val y : Int)
// 重载单目运算符 '-',就是重写操作符unaryMinus
operator fun Point.unaryMinus() = Point(-x,-y)
@RunWith(JUnit4::class)
class OperatorDemoTest{
@Test
fun test(){
val p = Point(1,1)
val np = -p
println(np) //输出 Point(x=-1, y=-1)
}
}
运算符和操作符的对应关系
运算符 | 操作符 |
---|---|
+T | T.unaryPlus() |
-T | T.unaryMinus() |
!T | T.not() |
T++ | T.inc() |
a-- | T.dec() |
T + E | T.plus(E) |
T - E | T.minus(E) |
.... 略 |
=== 和 !== 不可重载
5. 包声明
kotlin中目录与包的结构无需匹配,源代码可以在文件系统的任意位。
kotlin会默认导入一些基础包到每个kotlin文件中
kotlin.* // Int、Long等数据类型
kotlin.annotation.* // 注解
kotlin.collections.* // 集合
kotlin.comparisons.*
kotlin.io.* // 输入输出
kotlin.ranges.* //
kotlin.sequences.*
kotlin.text.*
// JVM平台默认包
java.lang.*
kotlin.jvm.*
// js 平台
kotlin.js.*