Programiranje

Zakaj Kotlin? Osem funkcij, ki bi lahko razvijalce Jave prepričale, da preklopijo

Kotlin, ki je bil uradno objavljen leta 2016, je v zadnjih letih pritegnil veliko pozornosti, zlasti odkar je Google napovedal podporo Kotlinu kot alternativi Javi na platformah Android. Z nedavno objavljeno odločitvijo, da Kotlin postane prednostni jezik za Android, se morda sprašujete, ali je čas, da se začnete učiti nov programski jezik. V tem primeru vam lahko ta članek pomaga pri odločitvi.

Kotlinova zgodovina izdaj

Kotlin je bil napovedan leta 2011, vendar se je prva stabilna izdaja, različica 1.0, pojavila šele leta 2016. Jezik je brezplačen in odprtokoden, razvil ga je JetBrains, Andrey Breslav pa vodilni jezikovni oblikovalec. Kotlin 1.3.40 je izšel junija 2019.

O Kotlinu

Kotlin je sodoben, statično natipkan programski jezik, ki vsebuje tako objektno usmerjene kot funkcionalne programske konstrukcije. Namenjen je več platformam, vključno z JVM, in je popolnoma interoperabilen z Javo. Kotlin bi v mnogih pogledih lahko izgledal, če bi bil zasnovan danes. V tem članku predstavljam osem lastnosti Kotlina, za katere verjamem, da jih bodo razvijalci Java z veseljem odkrili.

  1. Čista, kompaktna skladnja
  2. Enotni sistem (skoraj)
  3. Nična varnost
  4. Funkcije in funkcionalno programiranje
  5. Podatkovni razredi
  6. Razširitve
  7. Preobremenitev operaterja
  8. Predmeti na najvišji ravni in vzorec Singleton

Pozdravljen, svet! Kotlin proti Javi

Seznam 1 prikazuje obvezno "Pozdravljeni, svet!" funkcija napisana v Kotlinu.

Seznam 1. "Pozdravljen, svet!" v Kotlinu

 fun main () {println ("Pozdravljen, svet!")} 

Tako preprost je, da ta primer razkriva ključne razlike od Jave.

  1. glavni je funkcija najvišje ravni; to pomeni, da funkcij Kotlin ni treba ugnezditi znotraj razreda.
  2. Ne obstajajo javni statični modifikatorji. Kotlin ima modifikatorje vidnosti, vendar je privzeto javnosti in jih je mogoče izpustiti. Kotlin tudi ne podpira statično modifikator, vendar v tem primeru ni potreben, ker glavni je funkcija najvišje ravni.
  3. Od Kotlin 1.3 je parameter array-of-strings za glavni ni potreben in ga lahko izpustite, če ga ne uporabite. Po potrebi bi bil razglašen kot args: matrika.
  4. Za funkcijo ni določena nobena vrsta vrnitve. Kjer Java uporablja praznino, Uporablja Kotlin Enota, in če je vrsta vrnitve funkcije Enota, je lahko izpuščen.
  5. V tej funkciji ni podpičja. V Kotlinu so podpičja neobvezna, zato so prelomi vrstic pomembni.

To je pregled, vendar je treba izvedeti še veliko več o tem, kako se Kotlin razlikuje od Jave in jo v mnogih primerih izboljša.

1. Čistejša, bolj kompaktna skladnja

Javi pogosto očitajo, da je preveč podrobna, toda nekaj podrobnosti vam je lahko prijatelj, še posebej, če je izvorna koda bolj razumljiva. Izziv pri oblikovanju jezikov je zmanjšati besednost, hkrati pa ohraniti jasnost, in mislim, da je Kotlin daleč v smeri tega izziva.

Kot ste videli v seznamu 1, Kotlin ne zahteva podpičja in omogoča izpustitev vrste vrnitve za Enota funkcije. Oglejmo si še nekaj drugih funkcij, ki pomagajo Kotlin narediti čistejšo in bolj kompaktno alternativo Javi.

Sklepanje na tip

V Kotlinu lahko spremenljivko razglasite kot var x: Int = 5, ali pa lahko uporabite krajšo, a prav tako jasno različico var x = 5. (Medtem ko Java zdaj podpira var izjave, se je ta funkcija pojavila šele Java 10, dolgo potem, ko se je funkcija pojavila v Kotlinu.)

Kotlin tudi ima val deklaracije za spremenljivke samo za branje, ki so analogne spremenljivkam Java, ki so bile deklarirane kot dokončno, kar pomeni, da spremenljivke ni mogoče dodeliti. Seznam 2 daje primer.

Seznam 2. Spremenljivke samo za branje v Kotlinu

 val x = 5 ... x = 6 // NAPAKA: NE BOMO PRIPRAVLJENA 

Lastnosti v primerjavi s polji

Kjer ima Java polja, ima Kotlin lastnosti. Lastnosti so deklarirane in dostopne na način, podoben javnim poljem v Javi, vendar Kotlin za privzeto zagotavlja privzete izvedbe funkcij accessor / mutator; to pomeni, da zagotavlja Kotlin dobili () funkcije za val lastnosti in oboje dobili () in set () funkcije za var lastnosti. Prilagojene različice dobili () in set () po potrebi.

Večina lastnosti v Kotlinu bo imela podporna polja, vendar je mogoče določiti a izračunana lastnina, ki je v bistvu a dobili () funkcija brez zadnjega polja. Na primer, razred, ki predstavlja osebo, ima lahko lastnost za datum rojstva in izračunana lastnost za starost.

Privzeto v primerjavi z eksplicitnim uvozom

Java implicitno uvozi razrede, opredeljene v paketu java.lang, vendar je treba vse druge razrede izrecno uvoziti. Posledično se številne izvorne datoteke Java začnejo z uvozom razredov zbirk iz java.util, V / I razredi iz java.io, in tako naprej. Kotlin privzeto implicitno uvaža kotlin. *, kar je približno analogno uvozu Java java.lang. *, vendar Kotlin tudi uvaža kotlin.io. *, kotlin.collections. *in razredi iz več drugih paketov. Zaradi tega izvorne datoteke Kotlin običajno zahtevajo manj eksplicitnega uvoza kot izvorne datoteke Java, zlasti za razrede, ki uporabljajo zbirke in / ali standardni V / I.

Nobenega klica "novo" za konstruktorje ni

V Kotlinu ključna beseda novo ni potreben za ustvarjanje novega predmeta. Če želite poklicati konstruktor, uporabite ime razreda z oklepaji. Koda Java

 Študent s = nov Študent (...); // ali var s = nov študent (...); 

lahko v Kotlinu zapišemo takole:

 var s = Študent (...) 

Predloge nizov

Strune lahko vsebujejo izrazi predloge, ki so izrazi, ki se izračunajo z rezultati, vstavljenimi v niz. Izraz predloge se začne z znakom za dolar ($) in je sestavljen iz preprostega imena ali poljubnega izraza v zavitih oklepajih. Predloge nizov lahko skrajšajo izraze nizov, tako da zmanjšajo potrebo po eksplicitnem združevanju nizov. Kot primer je naslednja koda Java

 println ("Ime:" + ime + ", Oddelek:" + oddelek); 

lahko nadomesti krajša, a enakovredna Kotlinova koda.

 println ("Ime: $ ime, Oddelek: $ dept") 

Razširja in izvaja

Programerji Java vedo, da lahko razred podaljšati drug razred in izvajati enega ali več vmesnikov. V Kotlinu ni sintaksične razlike med tema dvema podobnima konceptoma; Kotlin za oba uporablja debelo črevo. Na primer koda Java

 javni razred Študent razširja Oseba izvaja Primerljivo 

bi bilo v Kotlinu zapisano takole:

 razred Študent: oseba, primerljiva 

Ni preverjenih izjem

Kotlin podpira izjeme na podoben način kot Java z eno veliko razliko - Kotlin nima preverjenih izjem. Čeprav so bile dobronamerne, so bile Javine preverjene izjeme zelo kritizirane. Še vedno lahko vrgel in ulov izjeme, vendar vas prevajalnik Kotlin ne sili, da bi ujeli nobenega od njih.

Destrukturiranje

Pomislite destrukturiranje kot preprost način razbitja predmeta na njegove sestavne dele. Deklaracija o destrukturiranju ustvari več spremenljivk hkrati. Seznam 3 spodaj vsebuje nekaj primerov. Za prvi primer predpostavimo to spremenljivko študent je primerek razreda Študent, ki je opredeljen v spodnjem seznamu 12. Drugi primer je vzet neposredno iz Kotlinove dokumentacije.

Seznam 3. Primeri destrukturiranja

 val (_, lName, fName) = študent // izvleči ime in priimek iz študentskega predmeta // podčrtaj pomeni, da student.id ne potrebujemo za ((ključ, vrednost) na zemljevidu) {// naredimo nekaj s ključem in vrednost} 

izjave in izrazi "če"

V Kotlinu, če se lahko uporablja za krmiljenje toka kot pri Javi, lahko pa se uporablja tudi kot izraz. Javni kriptični ternarni operater (?:) nadomesti z jasnejšim, vendar nekoliko daljšim če izraz. Na primer koda Java

 dvojno max = x> = y? x: y 

bi v Kotlinu zapisali takole:

val max = if (x> = y), potem x sicer y 

Kotlin je v tem primeru nekoliko bolj glasen kot Java, vendar je sintaksa verjetno bolj berljiva.

'ko' zamenja 'stikalo'

Moja najmanj priljubljena nadzorna struktura v jezikih, podobnih jeziku C, je stikalo izjavo. Kotlin nadomešča stikalo izjava z kdaj izjavo. Seznam 4 je vzet neposredno iz dokumentacije Kotlin. Opazite to odmor stavki niso potrebni in lahko enostavno vključite obsege vrednosti.

Seznam 4. Izjava "kdaj" v Kotlinu

 ko (x) {v 1..10 -> print ("x je v območju") v validNumbers -> print ("x velja")! v 10..20 -> print ("x je zunaj obsega ") else -> print (" nič od zgoraj ")} 

Poskusite prepisati seznam 4 kot tradicionalno C / Java stikalo izjavo, in dobili boste idejo, kako boljše nam je s Kotlinovo kdaj izjavo. Tudi podobno če, kdaj se lahko uporablja kot izraz. V tem primeru vrednost zadovoljene veje postane vrednost celotnega izraza.

Preklopi izraze v Javi

Java 12 je predstavil izraze stikal. Podobno kot pri Kotlinovem kdaj, Izrazi stikal Java ne zahtevajo odmor izjave in jih je mogoče uporabiti kot izjave ali izraze. Za več informacij o izrazih preklopov v Javi glejte "Zanka, preklop ali odmor? Odločanje in ponavljanje stavkov".

2. Enotni sistem (skoraj)

Java ima dva ločena sistema tipov, primitivne tipe in referenčne tipe (drugače, predmeti). Obstaja veliko razlogov, zakaj Java vključuje dva ločena tipa sistema. Pravzaprav to ni res. Kot je opisano v mojem članku Primer ohranjanja primitivov v Javi, je za primitivne tipe resnično en razlog - zmogljivost. Podobno kot Scala ima tudi Kotlin samo en sistem tipov, saj v bistvu ni razlike med primitivnimi tipi in referenčnimi tipi. Kotlin uporablja primitivne tipe, kadar je to mogoče, vendar bo po potrebi uporabil predmete.

Zakaj torej opozorilo "skoraj"? Ker ima Kotlin tudi specializirane razrede, ki predstavljajo nize primitivnih tipov brez režijskih stroškov samodejnega boksanja: IntArray, DoubleArray, in tako naprej. Na JVM, DoubleArray se izvaja kot dvojno []. Ali uporablja DoubleArray resnično spremeniš? Pa poglejmo.

Primerjalno merilo 1: Množenje matrice

V primeru primerov Java sem pokazal več primerjalnih rezultatov, v katerih sem primerjal Java primitive, razrede ovitkov Java in podobno kodo v drugih jezikih. Eno od meril je bilo preprosto množenje matrik. Za primerjavo zmogljivosti Kotlina z Javo sem za Kotlin ustvaril dve izvedbi množenja matrik, eno z uporabo Matrika in eno z uporabo Matrika. Seznam 5 prikazuje uporabo Kotlina z uporabo Matrika.

Seznam 5. Množenje matric v Kotlinu

 zabavno množenje (a: Array, b: Array): Array {if (! checkArgs (a, b)) throw Exception ("Matrice niso združljive za množenje") val nRows = a.size val nCols = b [0]. size val rezultat = matrika (nRows, {_ -> DoubleArray (nCols, {_ -> 0.0})}) za (NumberNum v 0 do nRows) {za (colNum v 0 do nCols) {var sum = 0.0 for (i v 0, dokler ne bo [0] .size) sum + = a [numberNum] [i] * b [i] [colNum] rezultat [rowNum] [colNum] = sum}} rezultat vrnitve} 

Nato sem primerjal uspešnost obeh različic Kotlina z Java dvojno in Java z Dvojno, uporabljam vsa štiri merila uspešnosti na mojem trenutnem prenosniku. Ker pri izvajanju vsakega primerjalnega preizkusa obstaja majhna količina "šuma", sem tri različice zagnal trikrat in povprečil rezultate, ki so povzeti v tabeli 1.

Tabela 1. Izvedbena uspešnost merila množenja matrike

Časovni rezultati (v sekundah)
Java

(dvojno)

Java

(Dvojno)

Kotlin

(DoubleArray)

Kotlin

(Matrika)

7.3029.836.8115.82

Ti rezultati so me nekoliko presenetili in narisal sem dva obroka. Najprej kotlinovsko delovanje DoubleArray je očitno boljši od zmogljivosti Kotlin Matrika, ki je očitno boljši od Java, ki uporablja razred ovojnic Dvojno. In drugič, zmogljivost Kotlina z uporabo DoubleArray je primerljiva - in v tem primeru nekoliko boljša od - zmogljivosti Java z uporabo primitivnega tipa dvojno.

Jasno je, da je Kotlin opravil veliko naloge pri optimizaciji potrebe po ločenih sistemih - z izjemo potrebe po uporabi razredov, kot so DoubleArray namesto Matrika.

Primerjalno merilo 2: SciMark 2.0

Moj članek o primitivih je vključeval tudi drugo, bolj znanstveno merilo, znano kot SciMark 2.0, ki je merilo Java za znanstveno in numerično računalništvo, ki ga ponuja Nacionalni inštitut za standarde in tehnologijo (NIST). Primerjalno merilo SciMark meri zmogljivost več računskih rutin in približno sešteje rezultat Mflops (milijoni operacij s plavajočo vejico na sekundo). Tako so za to merilo primernejše večje številke.

S pomočjo IntelliJ IDEA sem pretvoril Java različico merila SciMark v Kotlin. IntelliJ IDEA se samodejno pretvori dvojno [] in int [] v Javi do DoubleArray in IntArray v Kotlinu. Nato sem primerjal različico Java z uporabo primitivov z različico Kotlin DoubleArray in IntArray. Kot prej sem tri različice zagnal trikrat in povprečil rezultate, ki so povzeti v tabeli 2. Tabela še enkrat prikazuje približno primerljive rezultate.

Tabela 2. Učinkovitost izvajanja merila SciMark

Zmogljivost (v Mflops)
JavaKotlin
1818.221815.78
$config[zx-auto] not found$config[zx-overlay] not found