1.雙等于與三等于
fun main(args: Array<String>) {
val string1 : String = "Hello"
val string2 : String = String(charArrayOf('H','e','l','l','o'))
println(string1 == string2)
println(string1 === string2)
}
上面這段代碼的執(zhí)行結(jié)果:
true
false
Process finished with exit code 0
這其實(shí)很好理解,雙等于相當(dāng)于java中的equal,如果對比的類實(shí)現(xiàn)了equal這個方法,比如String類,實(shí)現(xiàn)的equal方法是對比內(nèi)容,所以例子中為true。如果是其他自定義類呢?因?yàn)閗otlin中的類都是繼承Any這個類,這個類中定義了equal這個方法,如果要實(shí)現(xiàn)自己的對比規(guī)則就需要重寫這個方法。三等于對比的是對象的內(nèi)存地址,很明顯string1和string2的內(nèi)存地址不是同一個。
class A(var name:String){
override fun equals(other: Any?): Boolean {
if(other is A)
return other.name == this.name;
return false
}
}
val a1 : A = A("a")
val a2 : A = A("a")
println(a1 == a2)
println(a1 === a2)
class B()
val b1 :B = B()
val b2 :B = B()
println(b1 == b2)
println(b1 === b2)
執(zhí)行結(jié)果:
true
false
false
false
上面的代碼對比就能發(fā)現(xiàn),感覺雙等于就是equal的操作符重載,那到底是不是呢?那么我們?nèi)タ聪翧ny的源碼!
public open class Any {
/**
* Indicates whether some other object is "equal to" this one. Implementations must fulfil the following
* requirements:
*
* * Reflexive: for any non-null reference value x, x.equals(x) should return true.
* * Symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
* * Transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true
* * Consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
*
* Note that the `==` operator in Kotlin code is translated into a call to [equals] when objects on both sides of the
* operator are not null.
*/
public open operator fun equals(other: Any?): Boolean
/**
* Returns a hash code value for the object. The general contract of hashCode is:
*
* * Whenever it is invoked on the same object more than once, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.
* * If two objects are equal according to the equals() method, then calling the hashCode method on each of the two objects must produce the same integer result.
*/
public open fun hashCode(): Int
/**
* Returns a string representation of the object.
*/
public open fun toString(): String
}
果然equal方法被operator關(guān)鍵字修飾了。ok,雙等于和三等于是怎么會事弄清楚了。
2.字符串相關(guān)
val a :Int = 1
val b :Int = 2
val s :String = a.toString() + " + "+ b +" = "+(a+b)
val ss :String = "$a + $b = ${a+b}"
println(s)
println(ss)
上面代碼兩個輸出是一樣的,都是“1 + 2 =3”,只不過一種用的是字符串拼接,另一種用的是字符串模版。字符串拼接在java中十分常見,也很方便,但是會產(chǎn)生臨時字符串,如果量大了以后會造成內(nèi)存抖動,對內(nèi)存十分不友好。而字符串模版的方式就不會有這個影響。
val rawString : String = """ ///////i'am kotlin \n\t\r """
三引號用開定義原始字符串,一切轉(zhuǎn)意字符會被原樣輸出。
因?yàn)樽址闹R點(diǎn)實(shí)在太多,有些跟java一樣,所以這里就暫時不做展開了。
3.簡單的類和對象
fun main(args : Array<String>){
val man:Man = Man("11","22",33)
val woman:Woman = Woman(44,"55",66)
}
open class Person constructor(var name:String ,var age:Int){
init {
println("Person is init")
}
}
class Man constructor(var a:String, name:String, age: Int):Person(name,age)
class Woman (var b:Int,name: String,age: Int):Person(name, age)
上面的代碼中可以看出了構(gòu)造器的標(biāo)準(zhǔn)寫法和簡寫法,以及init代碼塊的回調(diào)。這塊知識以后還有詳細(xì)介紹。
4.智能判空
val string1:String = "aaa"
val string2:String? = "bbb"
println(string1.length)
println(string2?.length)
println(string2!!.length)
在kotlin中String和String?可以看作兩個類型,String是不可空的字符串類,String?是可為空的字符串類。其實(shí)String和String?組合在一起才是一個真正的類。當(dāng)我們使用這些變量時,如果是不為空的變量正常使用,如果是可為空的變量要加個問號,要是不巧真的是空,那也不會拋出空指針。智能判空其實(shí)就是為了讓程序有更好的體驗(yàn),不至于一不小心就崩潰。還有一種雙嘆號的寫法,就是使用者責(zé)任制,放棄編譯器的空保護(hù),使用時確認(rèn)變量不會為空。
5.類型轉(zhuǎn)換
val man:Person= Man("11","22",33)
if (man is Man)
man.a
if (man is Woman)
man.b
使用3中的例子,用is這個關(guān)鍵字來判斷是否屬于目標(biāo)類,跟java中的instanceof一樣,但是kotlin比java多做了一步,當(dāng)if為true,對象實(shí)例將被自動轉(zhuǎn)化為目標(biāo)的類,不需要手動強(qiáng)轉(zhuǎn)的方式,所以man對象并沒有b屬性,但是編譯一樣能通過。
val m : Man = man as Man
val w : Woman? = man as? Woman
在java中類型的強(qiáng)制轉(zhuǎn)換無處不在,kotlin當(dāng)然也支持強(qiáng)轉(zhuǎn),使用as這個關(guān)鍵字,但是這種用法和java中強(qiáng)轉(zhuǎn)一樣都會失敗拋出類型轉(zhuǎn)換異常的問題。第二種用法就能很好的解決這個問題,man明顯不是Woman類型,那么w這個變量就會是空,并不會拋出異常。
6.區(qū)間
val range1 : IntRange = 0..10
val range2 : IntRange = 0 until 10
println(10 in range1)
println(10 in range2)
for (i in range1)
println(i)
range2.forEach { println(it) }
區(qū)間的概念在java中并沒有,range1是閉區(qū)間[0,10],而range2是半閉區(qū)間[0,10),in關(guān)鍵字可以作為contains的操作符重載,用來判斷是否包含該元素。區(qū)間遍歷的方式跟數(shù)組集合大同小異,那么他跟數(shù)組集合的區(qū)別主要是區(qū)間內(nèi)容時連續(xù)的。
7.數(shù)組
val ia : IntArray = intArrayOf(0,2,4,6,8)
val ca : CharArray = charArrayOf('k','o','t','l','i','n')
val sa : Array<String> = arrayOf("Hello","world")
println(ia.size)
println(ca[0])
sa[1] = "kotlin"
sa.forEach { println(it) }
在kotlin中,基本數(shù)據(jù)類型的數(shù)組系統(tǒng)已經(jīng)幫我們定義一些類,這個些優(yōu)化了一些自動拆裝箱的工作。其他用法很常規(guī),包括去長度,索引取值賦值,遍歷。