初學(xué)kotlin:kotlin與Java的區(qū)別
1.入口函數(shù)的區(qū)別:輸入輸出的區(qū)別kotlin中輸出用print(ln),并且一個(gè)語(yǔ)句完了之后不用加分號(hào)
kotlin中變量沒(méi)有類型,用val與var它會(huì)自動(dòng)推斷類型
val為不可變變量,相當(dāng)于常量 ;var為可變變量? ?
?指針常量值指針指向的對(duì)象不能變,但對(duì)象的內(nèi)容能變
//指針常量與常量指針與c語(yǔ)言中類似,常量指針與指針常量相反
2.kotlin中連接字符串用$符號(hào) ?如果要更改輸出的變量的值,需要加一個(gè)括號(hào)
3.數(shù)組的定義
Java中不可變數(shù)組的定義原則:必須要直接或間接明確元素有多少個(gè)
kotlin中用Array ?eg:val nums=arrayOf(1,2,.....)
4.輸出數(shù)組元素
Java中 ??eg:in nums[] ?for(int num: nums){System.out.println(num));
kotlin :for(i in 1..5){print(i)}//此時(shí)會(huì)打印出1,2,3,4,5 ???
若想要跳格輸出eg: for(i int 1..6 step 2){print(i)}//此時(shí)結(jié)果為 1,3,5
若不想要某個(gè)數(shù)如for(i int 1 until 5){print(i}此時(shí)不會(huì)輸出5
若想要遍歷數(shù)組元素for(num in nums){print(num)} 【nums為一個(gè)數(shù)組】 //這是for-each 方法,不關(guān)注索引
如想要反序則for(i in 5 down to 1)
若想要同時(shí)取出索引值和元素則for((i,num) in nums.withIndex()){println("i-num")
kotlin 用readLine ???變量說(shuō)明類型 eg:val a:Int=20 ???這里的20是Int類對(duì)象的一個(gè)值 【至于這個(gè)變量為什么能進(jìn)行加減乘除這些運(yùn)算,是因?yàn)镮n類有相應(yīng)的方法,其他類也是如此】 ?包裝類
kotlin中不支持強(qiáng)制類型轉(zhuǎn)換,但是類有相應(yīng)的方法
可選類型:String?表示有值或沒(méi)值null
!!強(qiáng)制表示肯定有值
address?.length 表示:1.如果有值,直接訪問(wèn)對(duì)象的length方法? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2.如果沒(méi)有值,后面的方法不執(zhí)行
內(nèi)存中存儲(chǔ)數(shù)據(jù)
堆
堆的特點(diǎn):堆的內(nèi)存由誰(shuí)創(chuàng)建的就由誰(shuí)釋放
用new 方法產(chǎn)生的對(duì)象放在堆里
棧
臨時(shí)變量作用域結(jié)束后由系統(tǒng)自己釋放
棧的特點(diǎn):First in ,Last out【FULO】先進(jìn)后出
Java和kotlin是跨平臺(tái)的高級(jí)語(yǔ)言
解析器能夠?qū)⒏呒?jí)語(yǔ)言轉(zhuǎn)換為JVM虛擬機(jī)能夠識(shí)別的語(yǔ)言 ?即.class 文件,字節(jié)碼文件
將文件轉(zhuǎn)換為字節(jié)碼文件右擊文件?open in > terminal>
硬盤和內(nèi)存的區(qū)別
如果要運(yùn)行一個(gè)文件,就會(huì)把硬盤里的文件加載到內(nèi)存中如果內(nèi)存不夠,會(huì)放到緩存中,如果緩存不夠,放到二級(jí)緩存以此類推
棧幀可以理解為方法
eg:public class Testperson {
public int dosomething(){
int a=1; ???????int b=2; ???????int c=(a+b)*5; ???????System.out.println(Thread.currentThread());//輸出當(dāng)前線程 ???????return c; ???}
public static void main(String args){
? ? Testperson testperson=new Testperson(); ???????int ?result=testperson.dosomething(); ???????System.out.println(result); ???}
}
訪問(wèn)權(quán)限:
public ??任意位置都可訪問(wèn):同一個(gè)包中、當(dāng)前類的子類、同一個(gè)文件、同一個(gè)模塊
private ??當(dāng)前類可以訪問(wèn),其他位置不能訪問(wèn)
protected ??當(dāng)前類、子類能訪問(wèn),同一個(gè)包能訪問(wèn),外部包、外部模塊不能訪問(wèn)
default ??與protected類似
Java中類創(chuàng)建后并不會(huì)立即占據(jù)內(nèi)存
Animal a1=new ?Animal() 經(jīng)歷的過(guò)程(僅僅是一個(gè)例子):
1.當(dāng)用new方法創(chuàng)建對(duì)象時(shí),在方法區(qū)尋找類的信息
2.如果沒(méi)有這個(gè)類,類加載器將當(dāng)前這個(gè)類的字節(jié)碼文件加載到內(nèi)存中 ???【這個(gè)類在內(nèi)存中的形式是什么? ??是類對(duì)象(類對(duì)象是虛的,但是它占據(jù)內(nèi)存)】
3.在堆中申請(qǐng)內(nèi)存空間
4.當(dāng)前的創(chuàng)建的對(duì)象的地址會(huì)放在操作數(shù)棧中
5.在當(dāng)前線程棧->方法棧幀->局部變量區(qū)申請(qǐng)內(nèi)存空間給a1
6.從操作棧中彈出頂部操作數(shù)(即4中創(chuàng)建的對(duì)象的地址)賦值給a1
構(gòu)造方法:為什么要有構(gòu)造方法?
1.默認(rèn)的無(wú)參構(gòu)造方法
類本身不知道如何創(chuàng)建自己的對(duì)象,對(duì)象本身是由Object(){}來(lái)創(chuàng)建,再由當(dāng)前這個(gè)類來(lái)初始化這個(gè)對(duì)象
2.重載的有參方法
(1)為了方便初始化值(2)在創(chuàng)建對(duì)象的同時(shí)給予某些需要的數(shù)據(jù)(時(shí)機(jī))
如何巧妙使用private來(lái)私有化構(gòu)造方法
給外部提供一個(gè)單例對(duì)象(整個(gè)程序運(yùn)行中這個(gè)類只有一個(gè)對(duì)象)
1.私有化構(gòu)造方法->外部無(wú)法創(chuàng)建這個(gè)類的對(duì)象
private Animal(){}
2.提供一個(gè)靜態(tài)成員屬性->靜態(tài)變量,只會(huì)初始化一次
private static Animal instance=new Animal();
3.給外部提供一個(gè)靜態(tài)方法->獲取這個(gè)對(duì)象
//注:這里沒(méi)有考慮內(nèi)存消耗和線程安全
public static Animal getInstance(){return instance }
加上static這個(gè)方法就變成了類方法,如果沒(méi)有static就是普通方法,需要?jiǎng)?chuàng)建一個(gè)對(duì)象去調(diào)用
4.外部獲取這個(gè)對(duì)象
Animal.getInstance();
系統(tǒng)類庫(kù)中一般以instance、shared、default開(kāi)頭的方法通常提供單例對(duì)象
kotlin(方法是函數(shù),但Java中叫方法而不叫函數(shù))
構(gòu)造函數(shù)
1.主構(gòu)造函數(shù)
當(dāng)沒(méi)有修飾符修飾構(gòu)造函數(shù)或沒(méi)有參數(shù)時(shí),可以省略;反之必須要寫(xiě)constructer()class Person constructor(){}
2.次構(gòu)造函數(shù)
constructer(name String):this(){]
注:a.次構(gòu)造函數(shù)必須直接調(diào)用主構(gòu)造函數(shù)
????????b.如果有父類,必須調(diào)用父類的構(gòu)造函數(shù)
//次構(gòu)造函數(shù)必須繼承主構(gòu)造函數(shù)
open class Father3 constructor(name: String)
?class Person8 constructor (name:String):Father3(name){
constructor(name:String,age:Int):this(name)
}
kotlin 實(shí)現(xiàn)單例(不完善版本)
class Person9 private construtor(){
companion object{//companion 這個(gè)相當(dāng)于Java中的static
private val defaultInstance=Person9()
fun getInstance():Person9{
return defaultInstance
}
}
}
注:java中的頂級(jí)類是Object類,kotlin中是Any類
kotlin 聲明屬性的方式1
//形式參數(shù)
?//臨時(shí)定義一個(gè)變量保存外部傳遞過(guò)來(lái)的值
?//注意:aName和aAge是臨時(shí)的,只能在兩種情況下可以使用
? ?//1. 聲明變量時(shí) 變量的初始值是外部通過(guò)主構(gòu)造函數(shù)傳遞過(guò)來(lái)
class L3Person constructor(aName:String,aAge:Int){
? var name:String = aName
?var age:Int = aAge
?}
? ?//2. 初始化塊中調(diào)用
? ?class L3Person constructor(aName:String,aAge:Int){
? ? var name:String = ""
? ?var age:Int = 0
? ? //主構(gòu)造函數(shù)調(diào)用之后 如果有聲明 就會(huì)調(diào)用init初始化塊
? ? ?init {
? ? name = aName
? ? ? ?age = aAge
? ?}
? ?}
聲明屬性的方式2
?//在主構(gòu)造函數(shù)中直接聲明屬性 用val var
? //需要在創(chuàng)建對(duì)象時(shí)給初始值的屬性才放到主構(gòu)造函數(shù)中
? ?class L3Person constructor(
? ? ?private var aName:String,
? ? val aAge:Int
? ?){
? ? ? var score = 98.5
?}
方法聲明
//無(wú)參 無(wú)返回值的函數(shù)
?//kotlin
?fun test():Unit{}
? //Java
public void test(){}
//有參 無(wú)返回值的函數(shù)
? //kotlin
?fun test1(a:Int,b:Int):Unit{}
? ?//java
?public void test1(int a,int b){}
? //有參 有返回值的函數(shù)
?//kotlin
? ?fun test2(a:Int,b:Int):Int{
? ? ? ?return a + b
? }
? //java
? ? public int test3(int a,int b){
? ? return ?a + b;
? }
? ?//如果函數(shù)實(shí)現(xiàn)只有一行 可以省略{}
?fun test3(a:Int, b:Int):Int = a+b
//如果函數(shù)實(shí)現(xiàn)只有一行 可以省略{}
? //返回值類型也可以省略
? ?fun test4(a:Int, b:Int) = a+b
Java如果方法是void類型的,它是沒(méi)有返回值的,但如果方法的實(shí)現(xiàn)即函數(shù)體里有return,此時(shí)這個(gè)return沒(méi)有返回值,它的作用是能夠退出當(dāng)前這個(gè)模塊
主構(gòu)造函數(shù)里聲明val/var表示是類的屬性
kotlin中返回值為空用Unit表示
最后在這里想要淺說(shuō)一下:
寫(xiě)程序有幾個(gè)階段:
1.在文本編輯器或IDE中編寫(xiě)代碼
2.預(yù)編譯.e
3.匯編:把高級(jí)語(yǔ)言轉(zhuǎn)化為匯編語(yǔ)言(匯編語(yǔ)言介于高級(jí)語(yǔ)言和機(jī)器語(yǔ)言之間).s
4.編譯:把匯編文件轉(zhuǎn)化為二進(jìn)制語(yǔ)言.o
5.鏈接:把所有.o文件連接成可執(zhí)行文件.exe、.dmg
6.運(yùn)行:得到對(duì)應(yīng)的結(jié)果