首先介紹下Kotlin在項目里面集成方法,集成方式很簡單,只需要按照下面操作就好
在根目錄的Build文件里面添加Kotlin支持
buildscript {
ext.kotlin_version = '1.3.31' //kotlin版本號
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
// kt
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
然后在app目錄的build文件添加
//這是一個Kotlin的擴展模塊,可以讓Activity自動關聯xml布局中的View而不需要findViewById。
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
添加lib
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
到此為止Kotlin在Java項目的集成就結束了
下面主要記錄Kotlin的基本使用語法
//java main 函數
public static void main(String[] args) {
}
//Kotlin main 函數
fun main(args: Array<String>) {
println("Hello world")//打印功能函數
}
下面解釋下kotlin的main函數
- fun:聲明函數的關鍵字
- main:函數名稱
- args:args就是參數名,跟java代碼中的args一樣
- : 冒號,在這里就是參數名稱和類型之間的間隔
- Array< String >:Array< T >,相當于java的數組(略微不同),T泛型(代表里面存什么類型數據)。而String和Java里面的String一樣(略微不同),整個意思跟java中的一樣,一個存放String類型的數組
基本數據類型 和Java基本一樣
var a: Byte = 2
var b: Short = 2
var c: Int = 2
var d: Long = 2L //長整型由大寫字母L標記
var e: Float = 2f //單精度浮點型由小寫字母f或大寫字符F標記
var f: Double = 2.0
數組
var int_array:Array<Int> = arrayOf(1, 2, 3)
var long_array:Array<Long> = arrayOf(1, 2, 3)
var float_array:Array<Float> = arrayOf(1.0f, 2.0f, 3.0f)
var double_array:Array<Double> = arrayOf(1.0, 2.0, 3.0)
var boolean_array:Array<Boolean> = arrayOf(true, false, true)
var char_array:Array<Char> = arrayOf('a', 'b', 'c')
定義局部變量
關鍵字 var 和 val
var 被它修飾的變量屬性可讀可寫
val 被它修飾的變量屬性可讀,但是只能被賦值一次(相當于java的final)
聲明變量需要在變量名稱前加上上面兩個關鍵字中的一個修飾
NULL檢查機制
Kotlin的空安全設計對于聲明可為空的參數,在使用時要進行空判斷處理,有兩種處理方式,字段后加!!像Java一樣拋出空異常,另一種字段后加?可不做處理返回值為 null或配合?:做空判斷處理
//類型后面加?表示可為空
var age: String? = "23"
//拋出空指針異常
val ages = age!!.toInt()
//不做處理返回 null
val ages1 = age?.toInt()
//age為空返回-1
val ages2 = age?.toInt() ?: -1
判斷是否為空
if(var_nullable == null)
安全調用
kotlin號稱空安全,就是有這個安全調用
var_int?.inc()
?.的意思就是:假如這個變量不是null的話就調用后面的函數(例子就是調用inc函數),否則就不調用
elvis操作符
在java中是不是有這樣的三元操作符
int a = 12;
int b = a > 12 ? a : 12;
在kotlin的判空調用就有類似的elvis操作符
val a = var_int?.inc() ?: -1
當var_int不是null的時候就調用inc(),假如是null的話,就返回-1給變量a
是不是跟java很像
!!
var_int!!.inc()
這個操作符的結果就是:當你的var_int 不是null的時候就正常調用inc(),是null的時候就拋出異常(npe)
字符串模板
$ 表示一個變量名或者變量值
$varName 表示變量值
${varName.fun()} 表示變量的方法返回值:
var a = 1
// 模板中的簡單名稱:
val s1 = "a is $a"
a = 2
// 模板中的任意表達式:
val s2 = "${s1.replace("is", "was")}, but now is $a"
when語法,像極了java中的switch語句,
fun printChar(cr: Char) {
when (cr) {
'a' -> {
println('a')
}
'b' -> {
println('b')
}
else -> {
println("不支持打印該字符")
}
}
}
For 循環
val items = listOf("apple", "banana", "kiwi")
for (item in items) {
println("-----$item")
}
for (i in items.indices) {
println("--hhh---${items[i]}--$i")
}
for (i in 1..10) {
if (i == 3) {
// i 為 3 時跳過當前循環,繼續下一次循環
continue
}
// i 為 6 時 跳出循環
if (i > 5) {
break
}
println("循環打印1到10----$i")
}
}
val items = listOf("apple", "banana", "kiwi")
for ((index, value) in items.withIndex()) {
println("TAGthe element at $index is $value")
}
Lambda 表達式實例
Lambda 表達式的簡單例子:
// 1. 不需要參數,返回值為 5
() -> 5
// 2. 接收一個參數(數字類型),返回其2倍的值
x -> 2 * x
// 3. 接受2個參數(數字),并返回他們的差值
(x, y) -> x – y
// 4. 接收2個int型整數,返回他們的和
(int x, int y) -> x + y
// 5. 接受一個 string 對象,并在控制臺打印,不返回任何值(看起來像是返回void)
(String s) -> System.out.print(s)
區間
var nums = 1 until 100 (1 100] 前閉后開
1..100 [1 100] 閉區間
step步長 如下例 每隔2 打印一次
var nums = 1..16
for (i in nums step 2) {
println(i)
}
nums.reversed() 反轉數組
//延遲初始化
確定某一個控件不會為空的時候可加上lateinit
private lateinit var refreshLayout: SmartRefreshLayout
下面這種寫法和上面一樣
private var refreshLayout: SmartRefreshLayout?=null
只是在使用的時候必須要refreshLayout?. 上面的這種寫法就可以預防少寫?.
函數定義使用關鍵字 fun,參數格式為:參數 : 類型
fun sum(a: Int, b: Int): Int { // Int 參數,返回值 Int
return a + b
}
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
// 如果是返回 Unit類型,則可以省略(對于public方法也是這樣):
public fun printSum(a: Int, b: Int) {
print(a + b)
}
定義常量與變量
可變變量定義:var 關鍵字
var <標識符> : <類型> = <初始化值>
不可變變量定義:val 關鍵字,只能賦值一次的變量(類似Java中final修飾的變量)
val <標識符> : <類型> = <初始化值>
NULL檢查機制
Kotlin的空安全設計對于聲明可為空的參數,在使用時要進行空判斷處理,有兩種處理方式,字段后加!!像Java一樣拋出空異常,另一種字段后加?可不做處理返回值為 null或配合?:做空判斷處理
//類型后面加?表示可為空
var age: String? = "23"
// !!. 拋出空指針異常
val ages = age!!.toInt()
// ?. 為空不做處理返回 null
val ages1 = age?.toInt()
//age為空返回默認值-1
val ages2 = age?.toInt() ?: -1
類型檢測及自動類型轉換
我們可以使用 is 運算符檢測一個表達式是否某類型的一個實例(類似于Java中的instanceof關鍵字
fun getStringLength(obj: Any): Int? {
if (obj is String) {
// 做過類型判斷以后,obj會被系統自動轉換為String類型
return obj.length
}
//在這里還有一種方法,與Java中instanceof不同,使用!is
// if (obj !is String){
// // XXX
// }
// 這里的obj仍然是Any類型的引用
return null
}
比較兩個數字
在 Kotlin 中,三個等號 === 表示比較對象地址,兩個 == 表示比較兩個值大小。
When 表達式
在 when 中,else 同 switch 的 default。如果其他分支都不滿足條件將會執行 else 分支。
when 也可以用來取代 if-else if鏈
var x = 1
when (x) {
1 -> {
Log.w("kotlin----", "x == 1")
}
2 -> {
Log.w("kotlin----", "x == 2")
}
else -> { // 注意這個塊
Log.w("kotlin----", "\"x 不是 1 ,也不是 2\"")
}
}
//when 中使用 in 運算符來判斷集合內是否包含某實例
val items = setOf("apple", "banana", "kiwi")
when {
"orange" in items -> Log.w("kotlin----","juicy")
"apple" in items -> Log.w("kotlin----","apple is fine too")
}
循環
val data = ArrayList<String>()
data.add("apple")
data.add("banana")
data.add("kiwi")
for (item in data) {
Log.w("kotlin----", "-----$item")
}
for (index in data.indices) {
Log.w("kotlin----", "-----" + array[index])
}
for ((index, item) in data.withIndex()) {
Log.w("kotlin----","the at $index is $item")
}
接口
interface testInter {
fun foo() {
print("B")
} // 帶{}默認已實現
fun bar()//未實現
}
內聯擴展函數之let
let擴展函數的實際上是一個作用域函數,當你需要去定義一個變量在一個特定的作用域范圍內,let函數的是一個不錯的選擇;let函數另一個作用就是可以避免寫一些判斷null的操作。
object.let{
it.todo()//在函數體內使用it替代object對象去訪問其公有的屬性和方法
}
//另一種用途 判斷object為null的操作
object?.let{//表示object不為null的條件下,才會去執行let函數體
it.todo()
}
內聯函數之with
它是將某對象作為函數的參數,在函數塊內可以通過 this 指代該對象。返回值為函數塊的最后一行或指定return表達式。
var user = UserInfoBean()
user.nickName = "111"
val result = with(user, {
Log.w("TAG", "---my name is " + this.nickName)
1000
})
Log.w("TAG", "--->" + result)
內聯擴展函數之run
適用于let,with函數任何場景。因為run函數是let,with兩個函數結合體,準確來說它彌補了let函數在函數體內必須使用it參數替代對象,在run函數中可以像with函數一樣可以省略,直接訪問實例的公有屬性和方法,另一方面它彌補了with函數傳入對象判空問題,在run函數中可以像let函數一樣做判空處理
var user = UserInfoBean()
user.nickName = "111"
val result = user.run {
Log.w("TAG", "--->" + "my name is $nickName")
1000
}
Log.w("TAG", "--->" + result)
--->my name is 111
--->1000
內聯擴展函數之apply
從結構上來看apply函數和run函數很像,唯一不同點就是它們各自返回的值不一樣,run函數是以閉包形式返回最后一行代碼的值,而apply函數的返回的是傳入對象的本身。
var user = UserInfoBean()
user.nickName = "111"
val result = user.apply {
Log.w("TAG", "--->" + "my name is $nickName")
1000
}
Log.w("TAG", "--->" + result)
--->my name is 111
--->com.zhenai.base.bean.UserInfoBean@60a7d7a
@JvmOverloads這個注解是用來做什么的呢?
@JvmOverloads注解的作用:在有默認參數值的方法中使用,Kotlin會暴露多個重載方法。
foo()
foo("a")
foo("aa", 1)
foo("aaa", 1, "cc")
@JvmOverloads
fun foo(a: String = "a", b: Int = 0, c: String = "c") {
println(a)
println(b)
println(c)
}
class MyLayout
@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0)
: RelativeLayout(context, attrs, defStyleAttr) {
/*
@JvmOverloads
constructor(context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0) : super(context, attributeSet, defStyleAttr)
*/
}
------相當Java中的:是不是很方便,再也不用寫那么多重載方法了。
public class MyLayout extends RelativeLayout {
public MyLayout(Context context) {
this(context, null);
}
public MyLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}