温馨提示
写博客是为了记录在开发过程中所涉及到的技术以及遇到的问题的解决,如果该博客对您有所帮助,希望可以点个关注/喜欢;如果您对文章中的内容有什么不同的见解,欢迎留言进行讨论。谢谢!
一、 Kotlin语法
1. 变量与常量
<修饰符> <变量/常量名>[:类型]=[值]
*注:[]中的内容可省略,编译器可进行类型推导得出
在一般情况下:[类型]可省略,编译器进行类型推导
* 常量:
//val 修饰的为常量,不可再次赋值
val FINAL_HELLO_WORLD :String = "Hello World"
val USER_TYPE = "Admin"
* 变量:
//var 修饰的为变量,值可变化
var index:Int =1
//index 自增
index++
var username="ZhangSan"
* 字符串模板:
在Kotlin中可使用字符串模板来实现字符串中输出变量/常量值
var username="ZhangSan"
fun main(args:Array<String>){
username = args[0]
println("欢迎 ${username} 登录系统!")
}
2. 函数(得函数者得天下)
- [函数修饰符] <fun>[函数名称]([参数列表])[:返回值类型]{[函数体]}
- [函数修饰符] <fun>[函数名称]([参数列表])=[表达式]
*注:[]中的内容可省略,编译器可进行类型推导得出
/**
* 根据时间字符串返回日期
*/
private fun getDate(dateStr:String): Date {
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
return sdf.parse(dateStr)
}
/**
* 传入两个整形数,计算他们的和并输出
*/
fun add(num1:Int,num2:Int){
println("$num1 + $num2 = ${num1+num2}")
}
/**
* 传入姓名,输出 Hi [传入的姓名]
*/
fun sayHi(name:String)=println("Hi $name")
- 匿名函数
匿名函数就是没有函数名称的函数,但是匿名函数必须赋值给一个变量/常量
/**
* 匿名函数
*/
val sayHi = fun(name:String)=println("Hi $name")
3. Lambda 表达式
Lambda 表达式 就是匿名函数
- 语法:{[参数列表] -> [函数体,最后一行是返回值]}
例如:
val sum = {a:Int,b:Int -> a+b}
- Lambda 表达式类型表示
/**
* 无参,返回值为Unit
*/
() -> Unit
/**
* 传入整型,返回一个整型
*/
(Int) -> Int
/**
* 传入字符串、Lambda表达式,返回Boolean
*/
(String,(String) -> String) -> Boolean
- Lambda 表达式的调用
用()进行调用
等价于 invoke()
val sum = {a:Int,b:Int -> a+b}
sum(2,3)
sum.invoke(2,3)
- Lambda 表达式的简化
函数参数调用时最后一个Lambda可以移出去
函数参数只有一个Lambda,调用时小括号可以省略
Lambda只有一个参数可以默认为it
入参、返回值与形参一致的函数可以用函数的引用的方式作为实参传入
val arr: Array<String> = arrayOf("1","s","sd","rer","54","65")
/*
* Lambda 表达式 ,传入it ,并且打印it
* Lambda只有一个参数可以默认为it
*/
arr.forEach({it -> println(it)})
/*
* 上面的Lambda 表达式简化后
* Lambda只有一个参数可以默认为it
* 函数参数调用时最后一个Lambda可以移出去
*/
arr.forEach(){println(it)}
/*
* 上面的Lambda 表达式简化后
* Lambda只有一个参数可以默认为it
* 函数参数只有一个Lambda,调用时小括号可以省略
*/
arr.forEach{println(it)}
/*
* 上面的Lambda 表达式简化后
* Lambda只有一个参数可以默认为it
* 入参、返回值与形参一致的函数可以用函数的引用的方式作为实参传入
*/
arr.forEach(::println)
/*
* 判断数组中值为rer 是跳出本次循环,继续下次循环,相当于continue
*/
arr.forEach ForEach@{
if(it == "rer") return@ForEach
println(it)
}
/*
* 判断数组中值为rer 是跳出循环,不再进行下面的循环,继续制作该循环后面的代码
*/
run breaking@ {
arr.forEach {
if(it == "rer") return@breaking
println(it)
}}
3. 类成员
- 属性:或者说成员变量,类范围内的变量
- 方法:或者说成员函数,类范围内的函数
函数和方法的区别:
函数强调功能本身,不考虑从属
方法的称呼通常是从类的角度出发
只是叫法不同而已
- 定义属性
构造方法参数中val/var 修饰的都是属性
类内部也可以定义属性
class Hello(val aFiled:Int,notAField:Int){
var anotherField:Float = 3f
}
- 属性访问控制
属性可以定义getter/setter
val a: Int=0
get()=field
var b: Float = 0f
get(){
return field / 3;
}
set(value){field = value}
- 属性初始化
属性的初始化尽量在构造方法中完成
无法在构造方法中初始化,尝试降级为局部变量
var 用 lateinit 延迟初始化,val 用 lazy 延迟初始化
可空类型谨慎用 null 直接初始化
4. 运算符( +-*/%^? )
官网定义
Expression | Translated to |
---|---|
+a | a.unaryPlus() |
-a | a.unaryMinus() |
!a | a.not() |
— | — |
a++ | a.inc() + see below |
a– | a.dec() + see below |
— | — |
a+b | a.plus(b) |
a-b | a.minus(b) |
a*b | a.times(b) |
a/b | a.div(b) |
a%b | a.rem(b),a.mod(b)(deprecated) |
a..b | a.rangeTo(b) |
— | — |
a in b | b.contains(a) |
a !in b | !b.contains(a) |
— | — |
a[i] | a.get(i) |
a[i,j] | a.get(i,j) |
a[i_1,…,i_n] | a.get(i_1,…,i_n) |
a[i] = b | a.set(i,b) |
a[i,j] = b | a.set(i,,j,b) |
a[i_1,…,i_n] =b | a.set(i_1,…,i_n,b) |
— | — |
a() | a.invoke() |
a(i) | a.invoke(i) |
a(i,j) | a.invoke(i,j) |
— | — |
a += b | a.plusAssign(b) |
a -= b | a.minusAssign(b) |
a *= b | a.timesAssign(b) |
a /= b | a.divAssign(b) |
a %= b | a.modAssign(b) |
- 基本运算符
任何类可以定义或者重载父类的基本运算符
通过运算符对应的具名函数来定义
对参数的个数做要求,对参数和返回值类型不做要求
不能像 Scala 一样定义人与运算符
/*
* 定义一个复数,实部与实部相加,虚部与虚部相加
*/
class Complex(var real: Double,var imaginary: Double){
operator fun plus(other: Complex):Complex{
return Complex(real+other.real,imaginary + other.imaginary)
}
override fun toString():String{
return "$real + ${imaginary}i"
}
}
fun main(args: Array<String>){
val c1 = Complex(3.0,4.0)//3.0+4.0i
val c2 = Cpmplex(2.0,7.5)//2.0+7.5i
println(c1 + c2)
}
- 中缀表达式
只有一个参数,且用infix 修饰的函数
class Book {
infix fun on(place:String){...}
}
Book() on "My Desk"
- 分支表达式
** if 表达式
if … else
if(a == b) ... else if(a == c) ... else ...
表达式与完备性
val x = if(b<0) 0 else b
val x = if(b<0)0 //错误,赋值时,分支必须完备
** when 表达式
加强版的 switch ,支持任意类型
支持纯表达式条件分支(类似if)
表达式与完备性特性
- 循环语句
基本写法:
for(element in elements) …
给任意类实现 Iterator 方法
val arr: Array<String> = arrayOf("1","s","sd","rer","54","65")
for(a in arr){
println(a)
}
for((index,value) in arr.withIndex()){
println("$index -> $value")
}
for(indexedValue in arr.withIndex()){
println("${indexedValue.index} -> ${indexedValue.value}")
}
class MyIterator(val iterator: Iterator<Int>){
operator fun next():Int{
return iterator.next
}
operator fun hasNext():Boolean{
return iterator.hasNext()
}
}
cal MyIntList{
private val list = ArrayList<Int>()
fun add(int: Int){
list.add(int)
}
fun remove(int: Int){
list.remove(int)
}
operator fun iterator():MyIterator{
return MyIterator(list.iterator())
}
}
fun main(args: Array<String>){
val list = MyIntList()
list.add(1)
list.add(2)
list.add(3)
for(i in list){
println(i)
}
}
/******** while *************/
var x=5
while(x>0){
println(x)
x--
}
do{
println(x)
x--
}while(x>0)
** 跳出或跳过循环
跳出,终止循环 break
跳过当前循环 continue
多层循环嵌套的终止结合标签使用
Outter@for(...){
Inner@while(i<0){
if(...) break@Outter
}
}
5. 异常捕获
使用 try{}catch(e: Exception){} 进行异常捕获
try{
//程序正常执行
}catch(e: Exception){
//程序出现异常,可根据异常类型捕获相应的异常
}finally{
//无论执行成功还是出现异常都会执行
}
6. 具名参数
给函数的实参附上形参
fun sum(arg1:Int,arg2:Int) = arg1 + arg2
sun(arg2=3,arg1=2)
7. 变长参数
使用 vararg 修饰
某个参数可以接受多个值
可以不为最后一个参数
如果传参是由歧义,需要使用具名参数
8. Spread Operator
使用 * 来展开
只支持展开Array
只用于变长列表的实参
val arr=intArrayOf(1,2,3,4,5)
fun printMethod(vararg arrs:Int){
arrs.forEach(::println)
}
printMethod(*arr)
9.默认参数
为函数参数指定默认值
可以为任意位置的参数指定默认值
传参时,如果有歧义,需要使用具名参数
val arr=intArrayOf(1,2,3,4,5)
fun printMethod(name:String = "admin",vararg arrs:Int){
arrs.forEach(::println)
}
printMethod(arrs=*arr)
10. 导出可执行程序
- 在build.gradle 中增加
apply plugin: 'application'
mainClassName = ""//程序入口类路径,Kotlin文件名后加 Kt
- gradle 刷新/同步
- gradle 中的distribution 中点击installDist得到可执行的文件
- 在项目目录下的build文件夹下的install文件夹下
//命令行输入:
# cd build/install/[项目名称]
# chmod 755 bin/[项目名称]
# bin/[项目名称]