Ohjelmointi

Miksi Kotlin? Kahdeksan ominaisuutta, jotka voivat saada Java-kehittäjät vaihtamaan

Virallisesti julkaistu vuonna 2016, Kotlin on herättänyt paljon huomiota viime vuosina, varsinkin kun Google ilmoitti tukevansa Kotlinia vaihtoehtona Javalle Android-alustoilla. Äskettäin ilmoitetun päätöksen kanssa tehdä Kotlinista ensisijainen kieli Androidille, saatat miettiä, onko aika aloittaa uuden ohjelmointikielen oppiminen. Jos näin on, tämä artikkeli voi auttaa sinua päättämään.

Kotlinin julkaisuhistoria

Kotlin ilmoitettiin vuonna 2011, mutta ensimmäinen vakaa julkaisu, versio 1.0, ilmestyi vasta vuonna 2016. Kieli on ilmainen ja avoin lähdekoodin, jonka on kehittänyt JetBrains ja sen johtavana kielisuunnittelijana toimii Andrey Breslav. Kotlin 1.3.40 julkaistiin kesäkuussa 2019.

Tietoja Kotlinista

Kotlin on moderni, staattisesti kirjoitettu ohjelmointikieli, joka sisältää sekä olio- että toiminnallisia ohjelmointirakenteita. Se on kohdistettu useille alustoille, mukaan lukien JVM, ja se on täysin yhteensopiva Java: n kanssa. Monilla tavoin Kotlin on se, miltä Java saattaa näyttää, jos se suunnitellaan tänään. Tässä artikkelissa esitän Kotlinin kahdeksan ominaisuutta, joiden uskon Java-kehittäjien olevan innoissaan löytämisessä.

  1. Puhdas, kompakti syntaksi
  2. Yhden tyyppinen järjestelmä (melkein)
  3. Ei mitään turvallisuutta
  4. Toiminnot ja toiminnallinen ohjelmointi
  5. Dataluokat
  6. Laajennukset
  7. Kuljettajan ylikuormitus
  8. Ylätason objektit ja Singleton-kuvio

Hei maailma! Kotlin vs. Java

Luettelossa 1 näkyy pakollinen "Hei, maailma!" Kotlinissa kirjoitettu toiminto.

Listaus 1. "Hei, maailma!" Kotlinissa

 hauska pää () {println ("Hei maailma!")} 

Niin yksinkertainen kuin se onkin, tämä esimerkki paljastaa tärkeimmät erot Java: sta.

  1. tärkein on ylätason toiminto; toisin sanoen Kotlin-toimintoja ei tarvitse sijoittaa luokan sisällä.
  2. Ei ole olemassa julkinen staattinen muokkaajat. Vaikka Kotlinilla on näkyvyyden muokkaajia, oletus on julkinen ja voidaan jättää pois. Kotlin ei myöskään tue staattinen muokkaaja, mutta sitä ei tarvita tässä tapauksessa, koska tärkein on ylätason toiminto.
  3. Kotlin 1.3: n jälkeen merkkijonojen matriisi-parametri tärkein ei vaadita, ja se voidaan jättää pois, jos sitä ei käytetä. Tarvittaessa se ilmoitetaan args: Taulukko.
  4. Funktiolle ei ole määritetty palautustyyppiä. Missä Java käyttää mitätön, Kotlin käyttää Yksikköja jos funktion palautustyyppi on Yksikkö, se voidaan jättää pois.
  5. Tässä toiminnossa ei ole puolipisteitä. Kotlinissa puolipisteet ovat valinnaisia, ja siksi rivinvaihdot ovat merkittäviä.

Se on yleiskatsaus, mutta on paljon enemmän opittavaa siitä, miten Kotlin eroaa Javasta ja monissa tapauksissa parantaa sitä.

1. Puhtaampi, kompaktimpi syntaksia

Jaavaa kritisoidaan usein liian sanallisuudesta, mutta jotkut sanat voivat olla ystäväsi, varsinkin jos se tekee lähdekoodista ymmärrettävämmän. Kielisuunnittelun haasteena on vähentää sanallisuutta samalla kun säilytetään selkeys, ja mielestäni Kotlin kulkee paljon eteenpäin tähän haasteeseen vastaamiseksi.

Kuten näet luettelosta 1, Kotlin ei vaadi puolipisteitä, ja se sallii palautustyypin jättämisen Yksikkö toimintoja. Tarkastellaan muutamia muita ominaisuuksia, jotka auttavat tekemään Kotlinista puhtaamman ja kompaktimman vaihtoehdon Java-ohjelmalle.

Tyyppinen päättely

Kotlinissa voit ilmoittaa muuttujan muodossa var x: Int = 5, tai voit käyttää lyhyempää mutta yhtä selkeää versiota var x = 5. (Vaikka Java tukee nyt var ilmoituksia, tämä ominaisuus ilmestyi vasta Java 10: ssä kauan sen jälkeen, kun ominaisuus oli ilmestynyt Kotlinissa.)

Kotlinilla on myös val vain luku -muuttujien ilmoitukset, jotka ovat analogisia Java-muuttujien kanssa lopullinen, eli muuttujaa ei voida määrittää uudelleen. Listaus 2 antaa esimerkin.

Listaus 2. Vain luku -muuttujat Kotlinissa

 val x = 5 ... x = 6 // VIRHE: EI KOOSTA 

Ominaisuudet vs. kentät

Jos Javalla on kenttiä, Kotlinilla on ominaisuuksia. Ominaisuudet ilmoitetaan ja niihin pääsee samalla tavalla kuin Javan julkiset kentät, mutta Kotlin tarjoaa oletusasetukset lisäominaisuus- / mutatointitoiminnoille ominaisuuksille; eli Kotlin tarjoaa saada() toiminnot val ominaisuudet ja molemmat saada() ja aseta() toiminnot var ominaisuudet. Räätälöidyt versiot saada() ja aseta() voidaan toteuttaa tarvittaessa.

Suurimmalla osalla Kotlinin kiinteistöistä on taustakentät, mutta on mahdollista määrittää a laskettu ominaisuus, joka on olennaisesti a saada() toiminto ilman taustakenttää. Esimerkiksi henkilöä edustavalla luokalla voi olla ominaisuus syntymäaika ja laskettu ominaisuus ikä.

Oletus vs. nimenomainen tuonti

Java tuo implisiittisesti paketissa määriteltyjä luokkia java.lang, mutta kaikki muut luokat on nimenomaisesti tuotava. Tämän seurauksena monet Java-lähdetiedostot alkavat tuoda kokoeluluokat java.util, I / O-luokat alkaen java.io, ja niin edelleen. Kotlin tuo oletusarvoisesti epäsuorasti kotlin. *, joka on suunnilleen analoginen Java-tuonnin kanssa java.lang. *, mutta myös Kotlin tuo kotlin.io. *, kotlin. kokoelmat. *ja luokkia useista muista paketeista. Tämän vuoksi Kotlinin lähdetiedostot vaativat tavallisesti vähemmän nimenomaista tuontia kuin Java-lähdetiedostot, erityisesti luokille, jotka käyttävät kokoelmia ja / tai tavallisia I / O-tiedostoja.

Rakentajille ei vaadita "uutta"

Kotlinissa avainsana Uusi ei tarvita uuden objektin luomiseen. Soittaaksesi rakentajalle, käytä vain luokan nimeä sulkeissa. Java-koodi

 Opiskelija s = uusi opiskelija (...); // tai var s = uusi opiskelija (...); 

voitaisiin kirjoittaa Kotlinissa seuraavasti:

 var s = Opiskelija (...) 

Merkkijonomallit

Merkkijonot voivat sisältää mallilausekkeet, jotka ovat lausekkeita, jotka arvioidaan merkkijonoon lisättyjen tulosten kanssa. Mallilauseke alkaa dollarin merkillä ($) ja koostuu joko yksinkertaisesta nimestä tai mielivaltaisesta lausekkeesta. Merkkijonomallit voivat lyhentää merkkijonolausekkeita vähentämällä nimenomaisen merkkijonon ketjutuksen tarvetta. Esimerkiksi seuraava Java-koodi

 println ("Nimi:" + nimi + ", osasto:" + osasto); 

voitaisiin korvata lyhyemmällä mutta vastaavalla Kotlin-koodilla.

 println ("Nimi: $ nimi, Osasto: $ dept") 

Laajentaa ja toteuttaa

Java-ohjelmoijat tietävät, että luokka voi pidentää toinen luokka ja toteuttaa yksi tai useampi rajapinta. Kotlinissa näiden kahden samanlaisen käsitteen välillä ei ole syntaktista eroa; Kotlin käyttää kaksoispistettä molempiin. Esimerkiksi Java-koodi

 julkinen luokka Opiskelija jatkuu Henkilökohtaiset välineet Vertailukelpoinen 

kirjoitettaisiin yksinkertaisemmin Kotlinissa seuraavasti:

 luokan opiskelija: Henkilö, vertailukelpoinen 

Ei tarkistettuja poikkeuksia

Kotlin tukee poikkeuksia Java-kaltaisella tavalla yhdellä suurella erolla - Kotlinilla ei ole tarkistettuja poikkeuksia. Vaikka Java oli tarkoittanut hyviä aikomuksia, sitä on kritisoitu laajasti. Sinä voit silti heittää ja saada kiinni poikkeuksia, mutta Kotlin-kääntäjä ei pakota sinua tarttumaan mihinkään niistä.

Rakenneuudistus

Ajatella tuhoaminen yksinkertaisena tapana hajottaa esine sen osiksi. Tuhoava ilmoitus luo useita muuttujia kerralla. Alla olevassa luettelossa 3 on muutama esimerkki. Ensimmäisessä esimerkissä oletetaan, että muuttuja opiskelija- on luokan esiintymä Opiskelija, joka on määritelty alla olevassa luettelossa 12. Toinen esimerkki on otettu suoraan Kotlinin dokumentaatiosta.

Luettelo 3. Rakenneuudistusesimerkit

 val (_, lName, fName) = opiskelija // poimi etu- ja sukunimi opiskelijaobjektista // alaviiva tarkoittaa, että emme tarvitse student.id for ((avain, arvo) kartalla) {// tee jotain avaimella ja arvo} 

'jos' lausunnot ja ilmaisut

Kotlinissa jos voidaan käyttää ohjausvirtaan kuten Java, mutta sitä voidaan käyttää myös lausekkeena. Java: n kryptainen kolminkertainen operaattori (?:) korvataan selkeämmällä, mutta hieman pidemmällä jos ilmaisu. Esimerkiksi Java-koodi

 kaksinkertainen max = x> = y? x: y 

kirjoitettaisiin Kotlinissa seuraavasti:

val max = if (x> = y), sitten x muu y 

Kotlin on tässä tapauksessa hieman sanallisempi kuin Java, mutta syntaksit ovat kiistatta luettavampia.

'kun' korvaa kytkimen '

Pienin suosikkini ohjausrakenne C-tyyppisillä kielillä on vaihtaa lausunto. Kotlin korvaa vaihtaa lausunto a kun lausunto. Listaus 4 on otettu suoraan Kotlinin dokumentaatiosta. Huomaa, että tauko lauseita ei vaadita, ja voit helposti sisällyttää arvoalueita.

Listaus 4. "kun" -lauseke Kotlinissa

 kun (x) {1: ssä - 10 -> tulosta ("x on alueella") voimassa olevilla numeroilla -> tulosta ("x on kelvollinen")! 10: ssä 20 -> tulosta ("x on alueen ulkopuolella ") else -> print (" mikään yllä olevista ")} 

Yritä kirjoittaa Listaus 4 uudestaan ​​perinteiseksi C / Javaksi vaihtaa lausunnon, ja saat käsityksen siitä, kuinka paljon paremmin meillä on Kotlinin kanssa kun lausunto. Myös samanlainen kuin jos, kun voidaan käyttää ilmaisuna. Tällöin tyydytetyn haaran arvosta tulee koko lausekkeen arvo.

Vaihda Java-lausekkeita

Java 12 esitteli kytkinlausekkeita. Samanlainen kuin Kotlin kun, Java: n kytkinlausekkeet eivät vaadi tauko lauseita, ja niitä voidaan käyttää lauseina tai ilmaisuina. Katso "Jakaaminen, vaihtaminen tai tauko? Lausekkeilla päättäminen ja iterointi" saadaksesi lisätietoja Java-lausekkeiden vaihtamisesta.

2. Yhden tyyppinen järjestelmä (melkein)

Java: lla on kaksi erillistä tyyppijärjestelmää, primitiiviset tyypit ja viitetyypit (eli objektit). On monia syitä, miksi Java sisältää kaksi erillistä järjestelmää. Itse asiassa se ei ole totta. Kuten artikkelissani on kuvattu, Primitiivien säilyttäminen Java: ssa, primitiivisille tyypeille on oikeastaan ​​vain yksi syy - suorituskyky. Samoin kuin Scala, Kotlinilla on vain yksi tyyppijärjestelmä, koska Kotlinissa ei ole oleellisesti eroa primitiivisten tyyppien ja vertailutyyppien välillä. Kotlin käyttää primitiivisiä tyyppejä mahdollisuuksien mukaan, mutta käyttää esineitä tarvittaessa.

Joten miksi "melkein" varoitus? Koska Kotlinilla on myös erikoisluokkia edustamaan primitiivisten tyyppien taulukoita ilman autoboxing-yläpuolella: IntArray, DoubleArray, ja niin edelleen. JVM: llä DoubleArray toteutetaan kaksinkertainen[]. Onko käyttää DoubleArray todella tehdä eroa? Katsotaan.

Vertailuarvo 1: Matriisikertaus

Tarkoittaessani Java-primitiivien tapaa esitin useita vertailutuloksia, joissa verrattiin Java-primitiivejä, Java-kääreen luokkia ja vastaavaa koodia muilla kielillä. Yksi vertailuarvoista oli yksinkertainen matriisikertaus. Kotlinin suorituskyvyn vertaamiseksi Java: iin loin Kotlinille kaksi matriisikertaistoteutusta, yhden käyttäen Taulukko ja yksi käyttää Taulukko. Luettelossa 5 näkyy Kotlin-toteutus käyttäen Taulukko.

Listaus 5. Matriisin kertolasku Kotlinissa

 hauska kertolasku (a: Array, b: Array): Array {if (! checkArgs (a, b)) heittää poikkeus ("Matriisit eivät ole yhteensopivia kertolaskuun") val nRows = a.koko val nCols = b [0]. size val result = Taulukko (nRows, {_ -> DoubleArray (nCols, {_ -> 0.0})}) (riviNum 0: sta nRows: iin) {for (colNum 0: sta nCols: iin) {var summa = 0,0 for (i 0: ssa, kunnes [0] .size) summa + = a [riviNum] [i] * b [i] [colNum] tulos [riviNum] [colNum] = summa}} palauttaa tuloksen} 

Seuraavaksi vertasin kahden Kotlin-version suorituskykyä Java-versioon kaksinkertainen ja Java kanssa Kaksinkertainen, käynnissä kaikki neljä vertailuarvoa nykyisellä kannettavalla tietokoneellani. Koska jokaisen vertailuarvon suorittamisessa on vähän "melua", juoksin kaikki versiot kolme kertaa ja keskiarvoistin tuloksista, jotka on esitetty yhteenvetona taulukossa 1.

Taulukko 1. Matriisikertomuksen vertailuarvon ajonaikainen suorituskyky

Ajoitetut tulokset (sekunteina)
Java

(kaksinkertainen)

Java

(Kaksinkertainen)

Kotlin

(DoubleArray)

Kotlin

(Taulukko)

7.3029.836.8115.82

Olin hieman yllättynyt näistä tuloksista, ja piirrän kaksi otosta. Ensinnäkin Kotlinin suorituskyky DoubleArray on selvästi parempi kuin Kotlinin suorituskyky Taulukko, joka on selvästi parempi kuin Java, joka käyttää kääre-luokkaa Kaksinkertainen. Toiseksi Kotlinin suorituskyky DoubleArray on verrattavissa - ja tässä esimerkissä hieman paremmin - Java-suorituskykyyn primitiivistä tyyppiä käyttämällä kaksinkertainen.

Kotlin on selvästikin tehnyt suuren työn optimoimalla erillistyyppisten järjestelmien tarpeen - lukuun ottamatta tarvetta käyttää luokkia, kuten DoubleArray sijasta Taulukko.

Vertailuarvo 2: SciMark 2.0

Alkuperäisartikkeliini sisälsi myös toisen, tieteellisemmän vertailuarvon, joka tunnetaan nimellä SciMark 2.0, joka on Java-vertailuarvo tieteelliselle ja numeeriselle laskennalle, jonka saa National Institute of Standards and Technology (NIST). SciMark-vertailuarvo mittaa useiden laskennallisten rutiinien suorituskykyä ja raportoi yhdistetyn pistemäärän likimääräisenä Mflops (miljoonia liukulukuoperaatioita sekunnissa). Siksi suuremmat luvut ovat parempia tälle vertailuarvolle.

IntelliJ IDEA: n avulla muutin SciMark-vertailuarvon Java-version Kotliniksi. IntelliJ IDEA muunnetaan automaattisesti kaksinkertainen[] ja int [] Java-kielellä DoubleArray ja IntArray Kotlinissa. Sitten verrattiin primitiivien Java-versiota Kotlin-versioon DoubleArray ja IntArray. Kuten aikaisemmin, juoksin molemmat versiot kolme kertaa ja keskiarvoistin tuloksista, jotka on esitetty yhteenvetona taulukossa 2. Taulukossa esitetään jälleen suunnilleen vertailukelpoiset tulokset.

Taulukko 2. SciMark-vertailuarvon ajonaikainen suorituskyky

Suorituskyky (Mflops-muodossa)
JavaKotlin
1818.221815.78