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.