內容 :
- 函式、變數、類、屬性以及列舉
- Kotlin 中的控制結構
- 智慧轉換
一 函式宣告
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}複製程式碼
函式的宣告以關鍵字 fun 開始,函式名稱緊隨其後:這個例子中函式名稱是 max ,接下來是括號括起來的引數列表。引數列表的後面跟著返回型別,他們之間用冒號隔開。假如沒有返回值可以直接不寫或者寫成Unit型別。
注意:這裡return後邊程式碼是表示式而不是語句,表示式有返回值,語句沒有返回值。而再Kotlin中基本,除了迴圈( for, do do/while )以外大多數控制結構都是表示式。
上邊函式還可以這樣寫:
fun max(a: Int, b: Int): Int = if (a > b) a else b複製程式碼
如果函式體寫在花括號中,我們說這個函式有程式碼塊體。如果它直接返回了個表示式,它就有表示式體。
還可以這樣寫:
fun max(a: Int, b: Int) = if (a > b) a else b複製程式碼
因為Kotlin有型別自動推導特性。
注意:只有表示式體函式的返回型別可以省略。對於有返回值的程式碼塊體函式, 必須顯式地寫出返回型別和 return 語句。
二 常量和變數
在 Kotlin中以關鍵字開始,然後是變數名稱, 最後可以加上型別(不加也可以)。宣告變數的關鍵字有兩個
- val (使用 val 宣告的變數不能在初始化之
後再次賦值。它對應的是 Java final 量。)
- var (這種變數的值可以被改變。這種宣告對
應的是普通(非 final )的 Java 量。)
如下:
fun ddd() {
//隱式宣告區域性常量,型別自動推導
val a = 1
//顯示宣告區域性變數
var b: Int = 2
//如果不能提供可以賦給這個常量的值的資訊,編譯器就無法推斷出它的型別,並且val只有一次賦值機會
val c: String
c = "Kotlin就是厲害"
}複製程式碼
注意: val 引用自身是不可變的,但是它指向的物件可能是可變的。如下程式碼完全有效
val array= arrayListOf<String>("1","2","3")
array.add("4")複製程式碼
不可變物件和可變物件我們之後再討論。
注意:編譯器只會根據初始化器來推斷變數的型別,在決定型別的時候不會考慮 後續的賦值操作。如下錯誤的寫法:
var b: Int = 2
b = "型別錯誤"複製程式碼
三 類
java中的類:
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}複製程式碼
使用Kotlin就變成了:
class Person(val name: String)複製程式碼
注意:從 Java otlin 的轉換過程中 public 修飾符消失了 。在 Kotlin 中,
public 是預設的可見性,所以你能省略它。
四 屬性
在類中宣告一個屬性和宣告一個變數一樣:使用val和var關鍵字。宣告成val的屬性是隻讀的,而var屬性是可變的。當你宣告屬性的時候,你就宣告瞭對應的get和set方法(只讀屬性有一個get,而可寫屬性既有get也有set)如:
class Person {
var name: String = "張三"
val isMan: Boolean = false
}
複製程式碼
當你使用這個類的屬性時候,內部其實是呼叫的對應的get和set方法,而是未呈現出來
var p = Person()
//設定值,內部其實是呼叫了set,只是未呈現
p.name = "張三"
//獲取值,內部其實是呼叫了get,只是未呈現
Log.e("rrrrr",p.name)複製程式碼
如果我們去呈現他的get和set方法的就像這樣:
class Person {
var name: String = "張三"
get(){
return field
}
set(value) {
field = value
}
val isMan: Boolean = false
get(){
return field
}
}複製程式碼
注意:需要解釋的是這個field ,你可以把field認為就是name,也可以把field認為是isMan,它的出現就是為了解決死迴圈,因為預設使用屬性,就是呼叫屬性的get方法。
4.2 自定義get和set方法
如建立一個長方形類,裡邊有一個欄位,是判斷長方形是否是正方形的標記,我們可以這樣寫:
class Rect(var w :Int ,var h:Int) {
val isSQ :Boolean
get() {
return w==h
}
}複製程式碼
呼叫:
var rect = Rect(10,10)
Log.e("rrrrrrr","${rect.isSQ}")複製程式碼
Log如下:
rrrrrrr: true
4.3 修改屬性的可見性
我們可以在自定義的get或者set方法前邊加上可見修飾符去修改屬性的可見性,訪問器的可見性預設與屬性的可見性相同。
五 列舉
Kotlin中使用了兩個關鍵字去宣告列舉,enum 和 class, enum是一個所謂的軟關鍵字:只有當它出現在class前面時才有特殊的意義,在其他地方可以把它當作普通的名稱使用。
enum class Colors() {
//建立列舉物件
Red(),Blue(),Black();
}複製程式碼
六 控制語句
6.1 when
when好比java中的switch,比switch強大之處,它也是一個表示式,有返回值,不僅可以傳遞常量,還可以傳遞物件。通過上邊列舉去選擇性返回一個數字,程式碼如下:
6.1.1傳遞常量
private fun select(color: Colors): Int {
return when (color) {
Colors.Blue->0
Colors.Black -> 1
Colors.Red -> 2
}
}複製程式碼
呼叫這個方法,傳遞的引數不同,獲取到的返回值也是不同的。上邊程式碼還可以寫成這樣:
fun select(color: Colors) = when (color) {Colors.Blue->0 ;Colors.Black -> 1 ;Colors.Red -> 2 }複製程式碼
6.1.2 傳遞物件
假設我們有這樣一個需求,用程式碼建立一個調色盤,傳遞一個倆個顏色的set集合物件,返回一個他們的綜合色,程式碼如下:
fun palette(color1: Color, color2: Color): String {
return when (setOf(color1, color2)) {
setOf(Color.Red, Color.Black) -> "藍色"
setOf(Color.Red, Color.Blue) -> "綠色"
else -> "未知顏色"
}
}複製程式碼
注意:
set集合這樣寫他們是相等的:
val set1 = setOf("1","22")
val set2 = setOf("22","1")
複製程式碼
但是這樣寫他們就是不相等:
val set1 = HashSet<String>()
set1.add("1")
set1.add("22")
val set2 = HashSet<String>()
set1.add("22")
set1.add("1")複製程式碼
在java中更是需要自己去迴圈比較是否相等。
而list集合不管怎麼樣去建立都是相等的:
var arr1 = ArrayList<String>()
arr1.add("11")
arr1.add("22")
var arr2 = ArrayList<String>()
arr2.add("11")
arr2.add("22")
var arr3 = listOf("11","22")
var arr4 = listOf("11","22")複製程式碼
在java中用equals方法判斷裡邊值是否相等
關於更多的集合的比較在後邊在去詳細說明,這裡先記下有這個情況!!!
6.2 if
6.2.1基本用法
上文已經簡單的使用了,if的基本用法:
fun max(a: Int, b: Int) = if (a > b) a else b複製程式碼
這個表示式體和三元運算子長的很像,因為在Kotlin中if是表示式有返回值 ,所以在Kotlin中沒有三元運算子的語法。
在java中型別轉換需使用instanceOf , 之後再去向下轉型。在kotlin中使用關鍵字is 判斷後,型別會自定轉換成你要轉換的型別方法。
這裡我們去建立一個父親介面,還有兩個兒子類有各種獨有的方法:
interface Father
class Son1:Father{ fun son1Method(){} }
class Son2:Father{ fun son2Method(){} }
複製程式碼
判斷是哪個兒子的方法:
fun who(aaa: Father) {
if (aaa is Son1){
aaa.son1Method()//這裡判斷是兒子1,只能呼叫兒子1的方法
}else if (aaa is Son2){
aaa.son2Method()//這裡是兒子2,只能呼叫兒子2的方法
}
}複製程式碼
如果想要顯示的轉換型別就需要使用 as關鍵字。
6.2.2 if和when之間轉換
上邊程式碼判斷是哪個兒子的方法,用when重構程式碼如下:
fun who(aaa: Father) {
when (aaa){
is Son1->aaa.son1Method()
is Son2->aaa.son2Method()
}
}複製程式碼
這裡更加說明when的強大之處,可以傳遞常量,物件,甚至是型別判斷
6.3 while
6.4 for
6.4.1基礎
for (a in 1..100){
}複製程式碼
起始值大於結束值用downTo:
for (a in 100 downTo 1){
}複製程式碼
每隔兩步一迴圈
for (a in 1..100 step 2 ){
}
for (a in 100 downTo 1 step 2){
}複製程式碼
step傳遞的是絕對值,和正序倒序無關,它會自動判斷是每加兩步還是每減兩步
如果迴圈區間想寫成前閉後開,你可以這樣:
for (a in 1 until 100){
}複製程式碼
小結:for迴圈必須使用關鍵字in ,至於區間可以在 .. 或者downTo 或者until之間最少選擇一個,step表示步長,和正負無關。
6.4.2迴圈map
迴圈map還是和java中有區別的,在java中迴圈map需要去通過鍵獲取值,而在kotlin中你可以一次全部迴圈處理,程式碼可以這樣寫:
val map = TreeMap<String,String>()
map.put("1","1.1")
for ((key,value) in map) {
Log.e("rrrr","key${key}===value${value}")
}複製程式碼
這使你更加容易去取到map中的值。
6.4.3迴圈arraylist:
val arr = arrayListOf("1","2")
//正常迴圈和java並無異樣
for (value in arr){
Log.e("rrr","value${value}")
}
//使用withIndex 迴圈,是迴圈帶有下邊的list集合
for ((index ,value) in arr.withIndex()){
Log.e("rrr","value${value}index${index}")
}複製程式碼
6.4.4 in關鍵字能用到哪些控制結構中
上邊迴圈for中使用了in。同時在if中也能用in使用in運算子來檢查一個值是否在區間中,或者它的逆運算,!n,來檢查這個值是否不在區間中。
val arr = arrayListOf("1","2")
if ("1" !in arr){
}複製程式碼
而且在when中也能使用in,程式碼和使用is是一樣的。
小結:
- 方法宣告的結構,以及表示式體和程式碼塊體。
- 常量和比變數的宣告,陣列不變,陣列裡內容可變
- 型別自動推導的便捷使用。
- 類的宣告,以及關鍵字class
- 屬性的宣告以及重寫get和set方法
- 列舉的宣告格式,軟關鍵字menu
- when控制結構,可以傳遞常量,物件,甚至可以使用is或者in關鍵字
- if控制結構,使用關鍵字is ,in, .. , downTo ,step ,until
- for控制結果,使用關鍵字 in, .. , downTo ,step ,until,迴圈map和迴圈帶下表的arraylist集合