隨著計(jì)算機(jī)語(yǔ)言的發(fā)展,從最初的C
、C++
、Java
等初始語(yǔ)言,近些年來(lái),又開(kāi)始流行一些被稱(chēng)之為現(xiàn)代編程語(yǔ)言,比如:Rust
、Go
、Kotlin
和TypeScript
等?,F(xiàn)代語(yǔ)言流行的原因,小編總結(jié)為以下幾點(diǎn):
- 入門(mén)更容易
- 類(lèi)型推斷
- 空指針安全
- 內(nèi)置的并發(fā)支持
- 減少模板代碼(簡(jiǎn)潔)
- 操縱集合更容易
- 更智能的垃圾回收
以上不一定非常全,但是一定程度上概括了現(xiàn)代語(yǔ)言的特點(diǎn),下面我們就基于Kotlin
和Java
的對(duì)比,來(lái)看下Kotlin
的優(yōu)勢(shì)。
new個(gè)對(duì)象
new
一個(gè)對(duì)象,是我們?cè)诰幊讨凶畛S玫牟僮髦?,讓我們先看下如何?code>Java中new
一個(gè)對(duì)象。
List<String> list =new ArrayList<String>();
list.add("hello world");
在Java
中,我們需要定義一個(gè)變量,然后通過(guò)new
關(guān)鍵字聲明一個(gè)ArrayList<String>
的示例,這樣我們就可以使用他了。
但是在Kotlin
,new
一個(gè)對(duì)象會(huì)更簡(jiǎn)潔。
var list:ArrayList<String> = ArrayList<String>()
直接省略了new關(guān)鍵字即可。
類(lèi)型推斷
對(duì)于以上的Kotlin
代碼,我們完全可以省略掉變量 :
后面的類(lèi)型聲明,因?yàn)?code>kotlin可以自己推斷出來(lái)。
val list = ArrayList<String>()
是不是覺(jué)得更簡(jiǎn)潔了?我們開(kāi)發(fā)的效率也更高了。
空指針安全
在Java
中,變量,方法的參數(shù)等都是可以為null
的,但是在Kotlin
中默認(rèn)是不允許的,通過(guò)這種強(qiáng)制的限制,更好的避免空指針異常。
var list = ArrayList<String>()
list = null
以上代碼,在編譯期你會(huì)得到一個(gè)錯(cuò)誤提示:
Null can not be a value of a non-null type ArrayList<String>
如果我們的確需要null
賦值怎么做呢?在Kotlin
中需要開(kāi)發(fā)者自己顯示聲明才可以。
var list:Array<String>? = null
如上所示,在類(lèi)型后加 ?
即可。但是注意,我們不提倡這種做法,在實(shí)際的開(kāi)發(fā)中,你會(huì)發(fā)現(xiàn) ?
大部分都是為了兼容Java
代碼使用的。
屬性
我們通常會(huì)把數(shù)據(jù)和對(duì)數(shù)據(jù)的處理封裝到一個(gè)類(lèi)中,如果類(lèi)中有私有字段,我們還需要提供getter
和setter
方法提供訪(fǎng)問(wèn)和修改字段的方法。
//Person.java
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//Main.java
public static void main(String[] args) {
Person p = new Person();
p.setName("張三");
System.out.println(p.getName());
}
以上是我們通過(guò)Java
實(shí)現(xiàn)的一個(gè)Person類(lèi),并且定義了 name 私有字段,同時(shí)提供了getter
和setter
方法,這樣我們才能夠使用它。
通過(guò)以上代碼,大家可以看到,我們?yōu)榱藢?shí)現(xiàn)一個(gè) name 的存儲(chǔ),寫(xiě)了很多代碼,如果一個(gè)類(lèi)存在很多字段,我們會(huì)寫(xiě)更多的不必要的getter
和setter
方法。
現(xiàn)在我們看在Kotlin
中如何實(shí)現(xiàn)上面的功能。
//Person.kt
class Person {
var name:String = ""
}
//main.kt
fun main(){
val p = Person()
p.name = "張三"
println(p.name)
}
是的,就是這么簡(jiǎn)單,只需要這么幾行代碼,就可以實(shí)現(xiàn)和Java
一樣的功能,因?yàn)?code>Kotlin可以幫我們自動(dòng)的生成getter
和setter
這些模板代碼,就省了我們很多事情,大大的提高了我們的開(kāi)發(fā)效率,并且整個(gè)代碼也更簡(jiǎn)潔。
這里需要注意的是,如果字段是val
聲明的,那么只會(huì)生成getter
方法,因?yàn)?code>val是不可修改的,等價(jià)于Java
中的final
修飾符;如果字段是var
的,可以同時(shí)生成getter
和setter
方法,這時(shí)候就可以對(duì)字段賦值了。
數(shù)據(jù)類(lèi)
Kotlin
的簡(jiǎn)潔不僅僅體現(xiàn)在getter
和setter
方法上,還有數(shù)據(jù)類(lèi)。一個(gè)數(shù)據(jù)類(lèi)是一個(gè)數(shù)據(jù)容器,它用來(lái)存放數(shù)據(jù)。
一個(gè)好的數(shù)據(jù)類(lèi)的聲明,不僅有私有的字段、getter
和setter
方法,還要有toString
、equals
和hashCode
方法的實(shí)現(xiàn),以便對(duì)他們進(jìn)行打印、比較以及更好的儲(chǔ)存在map
中。
還是以Person
類(lèi)為例,一個(gè)合格的數(shù)據(jù)類(lèi)代碼如下:
public static class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
}
看下我們Java
的實(shí)現(xiàn),需要有這么30多行代碼才能實(shí)現(xiàn)。如果我們使用Kotlin
會(huì)是怎樣的呢?
data class Person(val name: String) {}
只需要這么一行代碼,以上的Java
功能都會(huì)實(shí)現(xiàn),這里的關(guān)鍵在于一個(gè) data
修飾符,是不是很酸爽。
并發(fā)
Kotlin
提供了協(xié)程來(lái)實(shí)現(xiàn)并發(fā),相比Java
的Thread
和Executor
等來(lái)說(shuō),它更輕便,簡(jiǎn)潔。我們對(duì)比下并發(fā)的基本實(shí)現(xiàn)。
public static void main(String[] args) throws InterruptedException {
new MyThread().start();
System.out.println(Thread.currentThread().getName()+":main");
//保證JVM存活
Thread.sleep(1000);
}
private static class MyThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(500);
System.out.println(Thread.currentThread().getName()+":Thread");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
運(yùn)行查看輸出,我們發(fā)現(xiàn)MyThread
并沒(méi)有阻塞main
的執(zhí)行,也就是并發(fā)了。
main:main
Thread-0:Thread
但是要注意到,Java
使用了兩個(gè)線(xiàn)程,一個(gè)是main
,一個(gè)是Thread-0
。同樣的功能,我們現(xiàn)在使用kotlin
實(shí)現(xiàn)下:
fun main(){
runBlocking {
launch {
delay(500)
println("${Thread.currentThread().name}:Thread")
}
println("${Thread.currentThread().name}:main")
}
}
相比Java
來(lái)說(shuō)更簡(jiǎn)潔,而且我們看下打印的輸出:
main:main
main:Thread
竟然是在同一個(gè)線(xiàn)程上實(shí)現(xiàn)的并發(fā),少了一個(gè)線(xiàn)程的申請(qǐng)開(kāi)銷(xiāo),效率更高,這也是kotlin
提出協(xié)程的概念。如果我們不想讓它在main
線(xiàn)程上執(zhí)行,可以通過(guò)切換調(diào)度器來(lái)實(shí)現(xiàn)。
launch(Dispatchers.IO)
只需要把上面的代碼的launch
換成launch(Dispatchers.IO)
即可,這樣調(diào)度器就給我們分配了一個(gè)IO
的線(xiàn)程池來(lái)執(zhí)行我們的代碼。如果我們使用Java
來(lái)實(shí)現(xiàn),要自己定義線(xiàn)程池,還要提交Runnable
,整個(gè)代碼是非常多的。
main:main
DefaultDispatcher-worker-1:Thread
kotlin
的協(xié)程非常強(qiáng)大和簡(jiǎn)潔,通過(guò)以上的例子,不能完全展示它的特性,剩下的如協(xié)程上下文、調(diào)度器、Flow、通道等能力大家可以自己摸索。
小結(jié)
通過(guò)以上對(duì)比,我們應(yīng)該可以看到作為一門(mén)現(xiàn)代編程語(yǔ)言的特點(diǎn)和具備的優(yōu)勢(shì),而且關(guān)于Kotlin
好用的特性我們還沒(méi)有完全列舉完,比如便捷的集合操作、屬性委托、擴(kuò)展函數(shù)等等。
文章來(lái)源:www.toutiao.com/a6862537179189477901/
以上就是W3Cschool編程獅
關(guān)于Kotlin跟Java比起來(lái)有什么優(yōu)勢(shì)的相關(guān)介紹了,希望對(duì)大家有所幫助。