Programovanie

Prečo Kotlin? Osem funkcií, ktoré môžu vývojárov Java presvedčiť k zmene

Kotlin, ktorý bol oficiálne uvedený v roku 2016, v posledných rokoch priťahoval veľkú pozornosť, najmä preto, že Google oznámil podporu Kotlin ako alternatívy k Jave na platformách Android. S nedávno oznámeným rozhodnutím, aby sa Kotlin stal preferovaným jazykom pre Android, si možno hovoríte, či je čas začať sa učiť nový programovací jazyk. V takom prípade by vám tento článok mohol pomôcť rozhodnúť sa.

História vydania Kotlina

Kotlin bol oznámený v roku 2011, ale prvé stabilné vydanie, verzia 1.0, sa objavilo až v roku 2016. Jazyk je bezplatný a otvorený zdroj, ktorý vyvinula spoločnosť JetBrains s vedúcim jazykovým dizajnérom Andrey Breslav. Kotlin 1.3.40 bol vydaný v júni 2019.

O Kotlinovi

Kotlin je moderný, staticky napísaný programovací jazyk, ktorý obsahuje objektovo aj funkčne konštruované programovanie. Zameriava sa na niekoľko platforiem vrátane JVM a je plne interoperabilný s programom Java. V mnohých ohľadoch je Kotlin to, ako by mohla vyzerať Java, keby bola navrhnutá dnes. V tomto článku predstavujem osem funkcií Kotlinu, o ktorých verím, že ich vývojári Java budú nadšení.

  1. Čistá a kompaktná syntax
  2. Systém jedného typu (takmer)
  3. Nulová bezpečnosť
  4. Funkcie a funkčné programovanie
  5. Dátové triedy
  6. Prípony
  7. Preťaženie obsluhy
  8. Predmety najvyššej úrovne a vzor Singleton

Ahoj, svet! Kotlin verzus Java

Zoznam 1 zobrazuje povinné „Ahoj, svet!“ funkcia napísaná v Kotline.

Zoznam 1. „Ahoj, svet!“ v Kotline

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

Tento príklad je jednoduchý, takže odhaľuje kľúčové rozdiely od Javy.

  1. hlavný je funkcia najvyššej úrovne; to znamená, že funkcie Kotlin nemusia byť vnorené do triedy.
  2. Nie sú k dispozícii žiadne verejná statická modifikátory. Zatiaľ čo Kotlin má modifikátory viditeľnosti, predvolená hodnota je verejné a možno ich vynechať. Kotlin tiež nepodporuje statický modifikátor, ale v tomto prípade to nie je potrebné, pretože hlavný je funkcia najvyššej úrovne.
  3. Od verzie Kotlin 1.3 je parameter poľa reťazcov pre hlavný sa nevyžaduje a ak sa nepoužíva, môže sa vynechať. V prípade potreby by bol vyhlásený za args: Pole.
  4. Pre funkciu nie je zadaný žiadny návratový typ. Kde sa používa Java neplatný, Používa Kotlin Jednotka, a ak je návratový typ funkcie Jednotka, možno vynechať.
  5. V tejto funkcii nie sú zadané bodkočiarky. V Kotline sú bodkočiarky voliteľné, a preto sú zalomenia riadkov významné.

To je prehľad, ale je potrebné sa dozvedieť oveľa viac o tom, ako sa Kotlin líši od Javy a v mnohých prípadoch ju vylepšuje.

1. Čistšia a kompaktnejšia syntax

Java je často kritizovaná za to, že je príliš podrobná, ale určitá výrečnosť môže byť vaším priateľom, najmä ak robí zdrojový kód zrozumiteľnejším. Výzvou v jazykovom dizajne je znížiť výrečnosť pri zachovaní jasnosti a myslím si, že Kotlin ide dlhou cestou k splneniu tejto výzvy.

Ako ste videli v zozname 1, Kotlin nevyžaduje bodkočiarky a umožňuje vynechať návratový typ pre Jednotka funkcie. Uvažujme o niekoľkých ďalších funkciách, vďaka ktorým je Kotlin čistejšou a kompaktnejšou alternatívou k Jave.

Odvodzovanie typu

V Kotline môžete deklarovať premennú ako var x: Int = 5, alebo môžete použiť kratšiu, ale rovnako prehľadnú verziu var x = 5. (Zatiaľ čo Java teraz podporuje var deklarácie, táto funkcia sa objavila až v Jave 10, dlho potom, čo sa táto funkcia objavila v Kotline.)

Kotlin tiež má val vyhlásenia pre premenné iba na čítanie, ktoré sú analogické s premennými Javy, ktoré boli deklarované ako konečné, čo znamená, že premennú nemožno priradiť znova. Výpis 2 uvádza príklad.

Výpis 2. Premenné iba na čítanie v Kotline

 val x = 5 ... x = 6 // CHYBA: NESPRACUJE SA 

Vlastnosti verzus polia

Tam, kde má Java polia, má Kotlin vlastnosti. Vlastnosti sú deklarované a pristupuje sa k nim podobným spôsobom ako k verejným poliam v Jave, ale Kotlin poskytuje predvolené implementácie funkcií prístupového / mutačného nástroja pre vlastnosti; to znamená, že poskytuje Kotlin dostať () funkcie pre val vlastnosti a oboje dostať () a sada () funkcie pre var vlastnosti. Prispôsobené verzie servera dostať () a sada () môžu byť implementované v prípade potreby.

Väčšina nehnuteľností v Kotline bude mať podporné polia, ale je možné definovať a vypočítaná vlastnosť, čo je v podstate a dostať () funkcia bez podporného poľa. Napríklad trieda predstavujúca osobu môže mať vlastníctvo pre dátum narodenia a vypočítaná vlastnosť pre Vek.

Predvolené verzus explicitné importy

Java implicitne importuje triedy definované v balíku java.lang, ale všetky ostatné triedy musia byť explicitne importované. Výsledkom je, že veľa zdrojových súborov Java začína importom tried kolekcie z java.util, I / O triedy z java.ioa tak ďalej. Štandardne Kotlin implicitne importuje kotlin. *, čo je zhruba obdoba importu Java java.lang. *, ale Kotlin aj dováža kotlin.io. *, kotlin.collections. *a triedy z niekoľkých ďalších balíkov. Z tohto dôvodu zdrojové súbory Kotlin zvyčajne vyžadujú menej explicitných importov ako zdrojové súbory Java, najmä pre triedy, ktoré používajú kolekcie a / alebo štandardné I / O.

Pre konštruktérov nie je potrebné volať „nové“

V Kotline kľúčové slovo Nový nie je potrebný na vytvorenie nového objektu. Ak chcete zavolať konštruktéra, stačí použiť názov triedy so zátvorkami. Kód Java

 Študent s = nový Študent (...); // alebo var s = new Student (...); 

by sa dal v Kotline napísať takto:

 var s = Študent (...) 

Šnúrkové šablóny

Struny môžu obsahovať šablónové výrazy, čo sú výrazy, ktoré sa vyhodnocujú s výsledkami vloženými do reťazca. Výraz šablóny sa začína znakom dolára ($) a skladá sa buď z jednoduchého názvu, alebo z ľubovoľného výrazu v zložených zátvorkách. Šablóny reťazcov môžu skrátiť výrazy reťazcov znížením potreby explicitného zreťazenia reťazcov. Napríklad nasledujúci kód Java

 println ("Meno:" + meno + ", Oddelenie:" + odd.); 

by sa dal nahradiť kratším, ale ekvivalentným Kotlinovým kódom.

 println ("Meno: $ meno, Oddelenie: $ odd") 

Rozširuje a implementuje

Programátori Java vedia, že trieda môže predĺžiť iná trieda a realizovať jedno alebo viac rozhraní. V Kotline neexistuje žiadny syntaktický rozdiel medzi týmito dvoma podobnými konceptmi; Kotlin pre oba používa dvojbodku. Napríklad kód Java

 verejná trieda Študent rozširuje Osobné náradie Porovnateľné 

by bolo jednoduchšie napísané v Kotline takto:

 trieda Študent: Osoba, porovnateľný 

Žiadne začiarknuté výnimky

Kotlin podporuje výnimky podobným spôsobom ako Java s jedným veľkým rozdielom - Kotlin nemá skontrolované výnimky. Aj keď boli dobre zamýšľané, kontrolované výnimky Java boli všeobecne kritizované. Stále môžeš hodiť a chytiť výnimky, ale kompilátor Kotlin vás nenúti chytiť ani jednu z nich.

Deštrukturalizácia

Rozmýšľať o deštruktívne ako jednoduchý spôsob rozbitia objektu na jeho základné časti. Deklarácia deštrukcie vytvorí viac premenných naraz. Zoznam 3 uvedený nižšie poskytuje niekoľko príkladov. V prvom príklade predpokladajme túto premennú študent je inštancia triedy Študent, ktorý je definovaný v zozname 12 nižšie. Druhý príklad je prevzatý priamo z dokumentácie Kotlin.

Zoznam 3. Príklady deštrukturalizácie

 val (_, lName, fName) = študent // extrahovať meno a priezvisko zo študentského objektu // podčiarkovník znamená, že nepotrebujeme student.id pre ((kľúč, hodnota) v mape) {// urob niečo s kľúčom a hodnota} 

výroky a výrazy „ak“

V Kotline ak možno použiť na riadiaci tok ako v prostredí Java, ale dá sa použiť aj ako výraz. Tajomný ternárny operátor Java (?:) je nahradený jasnejším, ale o niečo dlhším ak výraz. Napríklad kód Java

 dvojnásobok max = x> = y? x: y 

bude napísané v Kotline takto:

val max = if (x> = y), potom x else y 

Kotlin je v tomto prípade o niečo podrobnejší ako Java, ale syntax je pravdepodobne čitateľnejšia.

„keď“ nahradí „prepínač“

Moja najmenej obľúbená štruktúra riadenia v jazykoch podobných jazyku C je prepínač vyhlásenie. Kotlin nahrádza prepínač vyhlásenie s a kedy vyhlásenie. Výpis 4 je prevzatý priamo z dokumentácie Kotlin. Všimni si prestávka vyhlásenia nie sú povinné a môžete ľahko zahrnúť rozsahy hodnôt.

Výpis 4. Výrok „keď“ v Kotline

 when (x) {in 1..10 -> print ("x is in the range") in validNumbers -> print ("x is valid")! in 10..20 -> print ("x is outside the range ") else -> print (" nič z vyššie uvedeného ")} 

Skúste zoznam 4 prepísať ako tradičný jazyk C / Java prepínač vyhlásenie, a získate predstavu o tom, ako lepšie sa máme s Kotlinovou lepšie kedy vyhlásenie. Tiež, podobné ak, kedy možno použiť ako výraz. V takom prípade sa hodnota spokojnej vetvy stane hodnotou celkového výrazu.

Prepínanie výrazov v prostredí Java

Java 12 predstavila výrazy prepínačov. Podobne ako u Kotlina kedy„Prepínacie výrazy Java nevyžadujú prestávka výroky a môžu sa použiť ako výroky alebo výrazy. Viac informácií o výrazoch prepínania v jazyku Java nájdete v časti „Opakovanie, prepínanie alebo prestávka? Rozhodovanie a opakovanie pomocou príkazov“.

2. Systém jedného typu (takmer)

Java má dva samostatné systémy typov, primitívne typy a referenčné typy (alias objekty, objekty). Existuje veľa dôvodov, prečo Java obsahuje dva systémy samostatného typu. To vlastne nie je pravda. Ako je uvedené v mojom článku Prípad zachovania primitívov v Jave, pre primitívne typy existuje skutočne jediný dôvod - výkon. Podobne ako Scala, Kotlin má iba jeden typový systém v tom, že v podstate nie je žiadny rozdiel medzi primitívnymi typmi a referenčnými typmi v Kotline. Kotlin používa primitívne typy, pokiaľ je to možné, ale v prípade potreby použije objekty.

Prečo je teda výhrada „takmer“? Pretože Kotlin má aj špecializované triedy, ktoré reprezentujú polia primitívnych typov bez réžie autoboxingu: IntArray, DoubleArraya tak ďalej. Na JVM DoubleArray je implementovaný ako dvojitý []. Má pomocou DoubleArray naozaj urobiť rozdiel? Pozrime sa.

Benchmark 1: Násobenie matíc

Pri príprave prípadu pre primitívy Java som ukázal niekoľko porovnávacích výsledkov porovnávajúcich primitívy Java, triedy Java wrapper a podobný kód v iných jazykoch. Jedným z benchmarkov bolo jednoduché násobenie matíc. Pre porovnanie výkonu Kotlin s Javou som vytvoril pre Kotlin dve implementácie násobenia matíc, jednu s použitím Pole a jeden pomocou Pole. Výpis 5 zobrazuje implementáciu Kotlin pomocou Pole.

Výpis 5. Násobenie matíc v Kotline

 zábavné násobenie (a: Array, b: Array): Array {if (! checkArgs (a, b)) throw Exception ("Matice nie sú kompatibilné s násobením") val nRows = a.size val nCols = b [0]. size val result = Array (nRows, {_ -> DoubleArray (nCols, {_ -> 0,0})}) for (rowNum in 0 until nRows) {for (colNum in 0 until nCols) {var sum = 0.0 for (i v 0 do a [0] .size) sum + = a [rowNum] [i] * b [i] [colNum] výsledok [rowNum] [colNum] = sum}} návratový výsledok} 

Ďalej som porovnal výkon dvoch verzií Kotlin s výkonom v Java dvojitý a Java s Dvojitý, prevádzkujúci všetky štyri štandardy na mojom súčasnom notebooku. Pretože pri spustení každého benchmarku existuje malé množstvo „šumu“, spustil som všetky verzie trikrát a spriemeroval som výsledky, ktoré sú zhrnuté v tabuľke 1.

Tabuľka 1. Runtime výkon porovnávacieho testu násobenia matíc

Časované výsledky (v sekundách)
Java

(dvojitý)

Java

(Dvojitý)

Kotlin

(DoubleArray)

Kotlin

(Pole)

7.3029.836.8115.82

Tieto výsledky ma trochu prekvapili a nakreslím si dva stánky so sebou. Po prvé, výkon Kotlin pomocou DoubleArray je jednoznačne lepší ako výkon Kotlina Pole, čo je jednoznačne lepšie ako v prípade Java pomocou triedy wrapper Dvojitý. A za druhé, výkon Kotlin pomocou DoubleArray je porovnateľný s - a v tomto príklade o niečo lepším ako - výkonom Java pomocou primitívneho typu dvojitý.

Je zrejmé, že Kotlin odviedol skvelú prácu pri optimalizácii potreby systémov samostatného typu - s výnimkou potreby používať triedy ako DoubleArray namiesto Pole.

Benchmark 2: SciMark 2.0

Môj článok o primitívnych prostriedkoch obsahoval aj druhý, vedeckejší benchmark známy ako SciMark 2.0, čo je benchmark Java pre vedecké a numerické výpočty dostupný od Národného ústavu pre štandardy a technológiu (NIST). Benchmark SciMark meria výkon niekoľkých výpočtových rutín a približné hlási zložené skóre Mflops (milióny operácií s pohyblivou rádovou čiarkou za sekundu). Pre túto referenčnú hodnotu sú teda lepšie väčšie čísla.

S pomocou IntelliJ IDEA som konvertoval Java verziu benchmarku SciMark na Kotlin. IntelliJ IDEA sa automaticky prevedie dvojitý [] a int [] v Jave do DoubleArray a IntArray v Kotline. Potom som porovnal verziu Java pomocou primitívov s verziou Kotlin pomocou DoubleArray a IntArray. Rovnako ako predtým som obe verzie spustil trikrát a spriemeroval som výsledky, ktoré sú zhrnuté v tabuľke 2. Tabuľka opäť ukazuje zhruba porovnateľné výsledky.

Tabuľka 2. Runtime výkon testovacej hodnoty SciMark

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