(一)Kotlin 基礎語法
文章目錄
一、 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. 函式(得函式者得天下)
- [函式修飾符] [函式名稱]([引數列表])[:返回值型別]{[函式體]}
- [函式修飾符] [函式名稱]([引數列表])=[表示式]
*注:[]中的內容可省略,編譯器可進行型別推導得出
/**
* 根據時間字串返回日期
*/
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 [email protected]{
if(it == "rer") [email protected]
println(it)
}
/*
* 判斷陣列中值為rer 是跳出迴圈,不再進行下面的迴圈,繼續製作該迴圈後面的程式碼
*/
run [email protected] {
arr.forEach {
if(it == "rer") [email protected]
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
多層迴圈巢狀的終止結合標籤使用
[email protected](...){
[email protected](i<0){
if(...) [email protected]
}
}
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/[專案名稱]