Bevezetés a Groovy nyelvbe

1. Áttekintés

A Groovy a JVM dinamikus, szkriptnyelve. Bájtkódolásra fordít, és tökéletesen keveredik a Java kóddal és könyvtárakkal.

Ebben a cikkben a Groovy néhány alapvető jellemzőjét vesszük szemügyre, beleértve az alapvető szintaxist, az irányítási struktúrákat és a gyűjteményeket.

Ezután megvizsgáljuk azokat a főbb jellemzőket, amelyek vonzóvá teszik a nyelvet, beleértve a semmilyen biztonságot, az implicit igazságot, az operátorokat és a karakterláncokat.

2. Környezet

Ha a Groovyt akarjuk használni a Maven projektekben, a következőket kell hozzáadnunk a pom.xml:

  // ... org.codehaus.gmavenplus gmavenplus-plugin 1.5 // ... org.codehaus.groovy groovy-all 2.4.10 

A legfrissebb Maven plugin itt található, és a nagyszerű itt.

3. Alapvető jellemzők

A Groovy számos hasznos funkcióval rendelkezik. Most nézzük meg a nyelv alapvető építőköveit, és hogy miben különbözik a Java-tól.

Most nézzük meg a nyelv alapvető építőköveit, és hogy miben különbözik a Java-tól.

3.1. Dinamikus gépelés

A Groovy egyik legfontosabb jellemzője a dinamikus gépelés támogatása.

A típusdefiníciók nem kötelezőek, és a tényleges típusokat futás közben határozzák meg. Vessünk egy pillantást erre a két osztályra:

osztály Kacsa {String getName () {'Duck'}} osztály Macska {String getName () {'Cat'}} 

Ez a két osztály ugyanazt határozza meg getName módszer, de ezt a szerződés nem határozza meg kifejezetten.

Most képzelje el, hogy van egy listánk tárgyakról, amelyek kacsákat és macskákat tartalmaznak getName módszer. A Groovy segítségével a következőket tehetjük:

Kacsa kacsa = új Kacsa () Macska macska = új Macska () def list = [kacsa, macska] lista. Minden {obj -> println obj.getName ()}

A kód összeáll, és a fenti kód kimenete a következő lenne:

Kacsa macska

3.2. Implicit igazság konverzió

A JavaScripthez hasonlóan Groovy minden objektumot logikai értékként értékel, ha szükséges, pl. amikor azt egy ha utasítás vagy az érték tagadásakor:

if ("hello") {...} if (15) {...} if (someObject) {...}

Néhány egyszerű szabályra emlékezni kell erről a konverzióról:

  • Nem üres Gyűjtemények, tömbök, térképek értékelik igaz
  • Matcher legalább egy mérkőzéssel értékeli igaz
  • Iterátorok és Felsorolás további elemekkel kényszerítik arra igaz
  • Nem üres Húrok, GStrings és CharSequences, kényszerítik őket igaz
  • A nullától eltérő számokat kiértékelik igaz
  • A nem null objektum-hivatkozásokat kényszerítik igaz

Ha testre akarjuk szabni az implicit igaz konverziót, meghatározhatjuk a sajátunkat asBoolean () módszer.

3.3. Behozatal

Egyes csomagokat alapértelmezés szerint importálunk, és nem kell őket kifejezetten importálnunk:

import java.lang. * import java.util. * import java.io. * import java.net. * import groovy.lang. * import groovy.util. * import java.math.BigInteger import java.math.BigDecimal

4. AST átalakulások

AST (Absztrakt szintaxis fa) átalakítások lehetővé teszik, hogy bekapcsolódjunk a Groovy-fordítási folyamatba és testre szabhassuk igényeinknek megfelelően. Ez fordítási időben történik, így az alkalmazás futtatásakor nincs büntetés. Létrehozhatjuk az AST transzformációinkat, de használhatjuk a beépítetteket is.

Létrehozhatjuk átalakításainkat, vagy hasznot húzhatunk a beépítettekből.

Vessünk egy pillantást néhány megjegyzésre, amelyet érdemes tudni.

4.1. Megjegyzés TypeChecked

Ez a kommentár arra kényszeríti a fordítót, hogy szigorúan ellenőrizze a jegyzetelt kódrészleteket. A típusellenőrzési mechanizmus kibővíthető, így akár szigorúbb típusellenőrzést is biztosíthatunk, ha szükséges, a Java-ban.

Vessünk egy pillantást az alábbi példára:

class Universe {@TypeChecked int answer () {"negyvenkettő"}}

Ha megpróbáljuk lefordítani ezt a kódot, akkor a következő hibát vesszük észre:

[Statikus típusellenőrzés] - A java.lang típusú érték nem adható vissza. String on met visszatérő típusú int

A @TypeChecked az annotáció osztályokra és módszerekre alkalmazható.

4.2. Megjegyzés CompileStatic

Ez a megjegyzés lehetővé teszi a fordító számára, hogy fordítási idő ellenőrzéseket hajtson végre, ahogy azt a Java kóddal végzik. Ezt követően a fordító statikus összeállítást hajt végre, megkerülve ezzel a Groovy metaobject protokollt.

Ha egy osztályhoz kommentár kerül, akkor a kommentált osztály összes metódusát, tulajdonságát, fájlját, belső osztályát stb. Ha egy metódust feljegyeznek, a statikus összeállítást csak azokra az elemekre (bezárások és névtelen belső osztályok) alkalmazzák, amelyeket az adott módszer bezár.

5. Tulajdonságok

A Groovy-ban létrehozhatunk POGO-kat (Plain Old Groovy Objects), amelyek ugyanúgy működnek, mint a Java Java POJO-i, bár kompaktabbak, mert getterek és beállítók automatikusan generálódnak a közvagyonhoz az összeállítás során. Fontos megjegyezni, hogy csak akkor generálódnak, ha még nincsenek meghatározva.

Ez rugalmasságot biztosít számunkra, hogy az attribútumokat nyílt mezőként definiáljuk, miközben megtartjuk azt a képességet, hogy felülírjuk a viselkedést az értékek beállításakor vagy megszerzésénél.

Tekintsük ezt az objektumot:

osztály Személy {karakterlánc neve karakterlánc vezetéknév}

Mivel az osztályok, mezők és módszerek alapértelmezett hatóköre a nyilvános - ez nyilvános osztály, és a két mező nyilvános.

A fordító ezeket privát mezőkké alakítja és kiegészíti getName (), setName (), getLastName () és setLasfName () mód. Ha meghatározzuk a szetter és getter egy adott mező esetében a fordító nem hoz létre nyilvános módszert.

5.1. Parancsikon jelölések

A Groovy parancsikonos jelölést kínál a tulajdonságok megszerzéséhez és beállításához. A getterek és beállítók hívásának Java-módja helyett használhatunk egy mezőszerű hozzáférési jelölést:

resourceGroup.getResourcePrototype (). getName () == SERVER_TYPE_NAME resourceGroup.resourcePrototype.name == SERVER_TYPE_NAME resourcePrototype.setName ("valami") resourcePrototype.name = "valami"

6. Operátorok

Vessünk egy pillantást a sima Java-ról ismert operátorokra.

6.1. Null-Safe Dereference

A legnépszerűbb a null-safe dereference operátor “?” amely lehetővé teszi, hogy elkerüljük a NullPointerException metódus meghívásakor vagy a nulla tárgy. Különösen hasznos láncolt hívásoknál, ahol a nulla érték előfordulhat a lánc egy pontján.

Például nyugodtan hívhatjuk:

Karakterlánc neve = személy? .Szervezés? .Szülő? .Név

A fenti példában, ha a személy, személy.szervezés, vagy szervezet.szülő vannak nulla, azután nulla visszatér.

6.2. Elvis Operator

Az Elvis üzemeltetője “?:”Lehetővé teszi, hogy sűrítsük a hármas kifejezéseket. Ez a kettő egyenértékű:

Karakterlánc neve = személy.név?: AlapértelmezettNév

és

Karakterlánc neve = személy.név? person.name: defaultName

Mindkettő hozzárendeli az értékét személy.név a névváltozóhoz, ha van Groovy igaz (ebben az esetben nem nulla és van egy nem nulla hossz).

6.3. Űrhajó-üzemeltető

Az űrhajó-üzemeltető “” olyan relációs operátor, amely úgy működik, mint a Java összehasonlítani() amely két objektumot összehasonlít és -1, 0 vagy +1 értéket ad vissza mindkét argumentum értékétől függően.

Ha a bal oldali argumentum nagyobb, mint a jobb, akkor az operátor 1-et ad vissza. Ha a bal argumentum jobb, mint a jobb, az operátor −1-et ad vissza. Ha az argumentumok megegyeznek, a 0 visszatér.

Az összehasonlító operátorok használatának legnagyobb előnye a nullák oly módon, hogy x y soha nem fog dobni egy NullPointerException:

println 5 null

A fenti példa ennek eredményeként 1-et nyomtat.

7. Húrok

A karakterlánc-literálok kifejezésének többféle módja van. A Java-ban alkalmazott megközelítés (dupla idézett karakterláncok) támogatott, de megengedett, hogy egyes idézőjeleket is használjon, ha ez előnyben részesül.

A többsoros karakterláncokat, amelyeket más nyelveken heredoknak is neveznek, szintén hármas (akár egy-, akár kettős) idézetekkel támogatják.

A többsoros karakterláncok, amelyeket más nyelveken heredoknak is neveznek, szintén hármas (akár egy-, akár kettős) idézetekkel támogatottak.

A dupla idézőjelekkel meghatározott karakterláncok az interpolációt támogatják a ${} szintaxis:

def name = "Bill Gates" def greeting = "Hello, $ {name}"

Valójában bármilyen kifejezés elhelyezhető a ${}:

def name = "Bill Gates" def greeting = "Helló, $ {name.toUpperCase ()}"

A dupla idézőjelű karakterláncot GString-nek nevezzük, ha tartalmaz kifejezést ${}, különben sima Húr tárgy.

Az alábbi kód a teszt sikertelensége nélkül fog futni:

def a = "hello" állítás a.class.name == 'java.lang.String' def b = 'helló' assert b.class.name == 'java.lang.String' def c = "$ {b} "érvényesítés c.class.name == 'org.codehaus.groovy.runtime.GStringImpl'

8. Gyűjtemények és térképek

Vessünk egy pillantást néhány alapvető adatstruktúra kezelésére.

8.1. Listák

Íme néhány kód, amellyel néhány elem hozzáadható egy új példányhoz Tömb lista Java-ban:

Lista lista = new ArrayList (); list.add ("Hello"); list.add ("Világ");

És itt van ugyanaz a művelet Groovy-ban:

Lista lista = ['Helló', 'Világ']

A listák alapértelmezés szerint típusok java.util.ArrayList és kifejezetten deklarálható a megfelelő konstruktor meghívásával is.

Nincs külön szintaxisa a Készlet, de használhatunk típust kényszerítés azért. Vagy használja:

Üdvözlet beállítása = ['Helló', 'Világ']

vagy:

def greeting = ['Hello', 'World'] beállítva

8.2. Térkép

A szintaxisa a Térkép hasonló, bár kicsit bőbeszédűbb, mert képesnek kell lenniünk kettőspontokkal elválasztott kulcsok és értékek megadására:

def kulcs = 'Key3' def aMap = ['Key1': 'Érték 1', Key2: 'Érték 2', (kulcs): 'Másik érték']

Az inicializálás után kapunk egy újat LinkedHashMap a bejegyzésekkel: Key1 -> Value1, Key2 -> Value 2, Key3 -> Egy másik érték.

Sokféleképpen férhetünk hozzá a térkép bejegyzéseihez:

println aMap ['Key1'] println aMap [kulcs] println aMap.Key1

9. Vezérlő szerkezetek

9.1. Feltételek: ha más

Groovy támogatja a feltételes ha más a várt szintaxis:

if (...) {// ...} else if (...) {// ...} else {// ...} 

9.2. Feltételek: kapcsolószekrény

A kapcsoló utasítás visszafelé kompatibilis a Java kóddal, így áteshetünk azokon az eseteken, amelyek ugyanazt a kódot osztják meg több mérkőzésre.

A legfontosabb különbség az, hogy a kapcsoló egyeztetést hajthat végre több különböző értéktípus ellen:

def x = 1.23 def result = "" switch (x) {case "foo": result = "found foo" break case "bar": eredmény + = "bar" töréses eset [4, 5, 6, 'inList'] : eredmény = "lista" töréseset 12..30: eredmény = "tartomány" töréses eset Szám: eredmény = "szám" töréses eset ~ / fo * /: eredmény = "foo regex" töréses eset {it <0}: / / vagy {x <0} eredmény = "negatív" törés alapértelmezett: eredmény = "alapértelmezett"} println (eredmény)

A fenti példa kinyomtatható szám.

9.3. Hurkok: míg

Groovy támogatja a szokásosat míg hurkok, mint a Java:

def x = 0 def y = 5, míg (y--> 0) {x ++}

9.4. Hurkok: mert

Groovy magáévá teszi ezt az egyszerűséget és bátorítja mert hurkok ezt a struktúrát követve:

for (változó iterálható) {body}

A mert hurok ismétlődik iterálható. A gyakran használt iterable tartományok, gyűjtemények, térképek, tömbök, iterátorok és felsorolások. Valójában bármely tárgy lehet iterálható.

A test körüli zárójel nem kötelező, ha csak egy utasításból áll. Az alábbiakban bemutatunk példákat a hatótávolság, lista, sor, térkép, és húrok:

def x = 0 for (i in 0..9) {x + = i} x = 0 for (i in [0, 1, 2, 3, 4]] {x + = i} def tömb = (0. .4) .toArray () x = 0 (i a tömbben) {x + = i} def map = ['abc': 1, 'def': 2, 'xyz': 3] x = 0 (e térképen) {x + = e.érték} x = 0 for (v a map.values ​​()) {x + = v} def text = "abc" def list = [] for (c szövegben) {list. add (c)}

Az objektum iterációja teszi a Groovyt for-hurkoljon egy kifinomult vezérlési struktúrát. Érvényes megfelelője annak, ha olyan módszereket használunk, amelyek egy bezárással rendelkező objektum felett iterálnak, például a Gyűjtemény mindegyik módszer.

A fő különbség az, hogy a test a mert a hurok nem záródás, ez azt jelenti, hogy ez a test egy blokk:

(x 0..9-ben) {println x}

mivel ez a testület bezárás:

(0..9). Minden {println it}

Annak ellenére, hogy hasonlónak tűnnek, építésükben nagyon különböznek egymástól.

A záróelem egy saját tárgy, és különböző tulajdonságokkal rendelkezik. Meg lehet építeni egy másik helyen, és átadható a minden egyes módszer. A test azonban for-hurok közvetlenül generálódik bytecode megjelenési pontján. Különleges hatókörszabályok nem érvényesek.

10. Kivételek kezelése

A nagy különbség az, hogy az ellenőrzött kivételek kezelése nem érvényesül.

Az általános kivételek kezeléséhez elhelyezhetjük a potenciálisan kivételeket okozó kódot a próbáld / fogd Blokk:

próbáld meg a {someActionThatWillThrowAnException ()} catch (e) // naplózni a hibaüzenetet, és / vagy valamilyen módon kezelni}

Ha nem deklaráljuk az általunk elkapott kivétel típusát, akkor itt minden kivétel megfogható.

11. Zárások

Egyszerűen fogalmazva: a bezárás a futtatható kód névtelen blokkja, amelyet át lehet adni a változóknak, és az adatokhoz abban a kontextusban fér hozzá, ahol meghatározták.

Hasonlítanak a névtelen belső osztályokhoz is, bár nem valósítanak meg interfészt, és nem bővítik ki az alaposztályt. Hasonlóak a Java-ban található lambdákhoz.

Érdekes módon a Groovy teljes mértékben kihasználhatja a lambdák, különösen a streaming API támogatására bevezetett JDK-kiegészítések előnyeit. Mindig használhatunk bezárásokat, ahol lambda kifejezések várhatók.

Vegyük figyelembe az alábbi példát:

def helloWorld = {println "Hello World"}

A változó Helló Világ most hivatkozást tartalmaz a bezárásra, és úgy tudjuk végrehajtani, hogy felhívjuk hívás módszer:

helloWorld.call ()

A Groovy segítségével természetesebb módszerrel használhatjuk a hívás szintaxisát - ez meghívja a hívás módszer számunkra:

Helló Világ()

11.1. Paraméterek

A módszerekhez hasonlóan a lezárásoknak is lehetnek paramétereik. Három változat létezik.

Az utóbbi példában, mivel nincs semmi deklarációs állandó, ezért csak egy paraméter van az alapértelmezett névvel azt. A módosított bezárás, amely kinyomtatja az elküldött adatokat,

def printTheParam = {println it}

Nevezhetnénk így:

printTheParam ('hello') printTheParam 'hello'

Paraméterekre számíthatunk a bezárásokban is, és átadhatjuk őket, amikor hívunk:

def teljesítmény = {int x, int y -> visszatér Math.pow (x, y)} println teljesítmény (2, 3)

A paraméterek típusdefiníciója megegyezik a változókkal. Ha definiálunk egy típust, akkor csak ezt a típust használhatjuk, de megadhatjuk és átadhatunk bármit, amit csak szeretnénk:

def say = {what -> println what} say "Hello World"

11.2. Opcionális visszatérés

A bezárás utolsó nyilatkozata implicit módon visszaküldhető anélkül, hogy visszaírási nyilatkozatot kellene írni. Ez felhasználható a kazánlap kódjának minimálisra csökkentésére. Így egy szám négyzetét kiszámító lezárás a következőképpen rövidíthető:

def négyzet = {it * it} println négyzet (4)

Ez a lezárás az implicit paramétert használja azt és az opcionális visszatérési nyilatkozatot.

12. Következtetés

Ez a cikk gyors bemutatást adott a Groovy nyelvről és annak legfontosabb jellemzőiről. Először olyan egyszerű fogalmak bevezetésével kezdtük meg, mint az alapszintaktika, a feltételes utasítások és az operátorok. Bemutattunk néhány fejlettebb funkciót is, például üzemeltetőket és bezárásokat.

Ha további információt szeretne találni a nyelvről és annak szemantikájáról, akkor keresse fel közvetlenül a hivatalos oldalt.