📜 ⬆️ ⬇️

Groovy in 15 Minutes Overview

Groovy is an object-oriented programming language developed for the Java platform as an alternative to the Java language with Python, Ruby and Smalltalk features.

Groovy uses Java-like syntax with dynamic JVM bytecode compilation and works directly with other Java code and libraries. The language can be used in any Java project or as a scripting language.

Groovy features (distinguishing it from Java):
')
- Static and dynamic typing
- Built-in syntax for lists, associative arrays, arrays and regular expressions
- Closures
- Overload operations

[ http://ru.wikipedia.org/wiki/Groovy ]

Moreover, java code is almost always a valid groovy code.


Installation


To install, you need to download the archive from the office. unpack it into a convenient place and add the GROOVY_HOME environment variable, and add the path to the groovy / bin in the PATH:
export GROOVY_HOME=~/path/to/groovy/ export PATH=$GROOVY_HOME/bin:$PATH 


In NetBeans IDE 7.0, groovy support comes out of the box, for the Eclipse IDE there is a very good plugin that you can get here .

Groovy


The most important difference from java: in Groovy, everything is an object. All primitive types are immediately packed into objects. Those. "Int x" is actually "Integer x"

 println 1.class int a = 10 println a.class 


 class java.lang.Integer class java.lang.Integer 


It should not be forgotten that all packaging types are immutable, therefore every time a new object is created during any calculation.

Groovy strings


1) Java Strings - single quoted strings
2) Groovy Strings, they are also GStrings - in normal quotes
You can insert parameters into groovy lines, you cannot insert them into regular lines.

 javaString = 'java' groovyString = "${javaString}" j = '${javaString}' bigGroovyString = """ ${javaString} ${groovyString} ${j} ${2 + 2} """ println bigGroovyString 

  java java ${javaString} 4 


The lines apply operations + and *
 groovy:000> a = "a" ===> a groovy:000> a + "123" ===> a123 groovy:000> a * 5 ===> aaaaa 


++ and - - are also applicable to strings (since operator overloading is supported in groovy)
 groovy:000> a = 'abc' ===> abc groovy:000> a++ ===> abd groovy:000> a-- ===> ab 


Groovy has support for regular expressions at the level of language constructs:
 groovy:000> r =~ '^a$' ===> java.util.regex.Matcher[pattern=^a$ region=0,1 lastmatch=] 


Native support for maps + lists


The dictionaries (maps) and lists are also supported at the level of language constructions:
 groovy:000> a = [1, 3, 5] ===> [1, 3, 5] groovy:000> b = [1: true, 0: false] ===> {1=true, 0=false} 


Ranges


You can access the list items in groovy as follows:
 groovy:000> a = "0123456789" ===> 0123456789 groovy:000> a[1..4] ===> 1234 groovy:000> a[1..-1] ===> 123456789 groovy:000> a[-1..0] ===> 9876543210 groovy:000> a[1..<9] ===> 12345678 groovy:000> a[1, 3, 5] ===> 135 groovy:000> b = 1..5 ===> 1..5 groovy:000> a[b] ===> 12345 


Range is the same object, so constructs like the latter are possible. Negative indices, as in python, return items from the end of the list.

Range can be made up of lines:
 groovy:000> 'a'..'aa' ===> a..aa 


Moreover, range can be made from any object that has the methods next () and prev ().

Cycles


The cycles in groovy are exactly the same as in java, plus another “foreach” is added to them:
 for (i in 0..9) { print i } for (int i = 0; i < 9; ++i) { print i } for (Integer i : 0..9) { print i } 


Functions


 def functionA(argA) { print ArgA } int functionB(int argB) { print argB return argB } String fuctionC() { "Hello World" } 


The return keyword is optional; by default, the value of the last variable in the function will be returned.

Closures


Closure is an anonymous function.
 def cl = {a, b -> println a println b } cl(1, 2) 


Many objects have methods, which as parameters are passed to closure:
 1.upto 10, { print it } 10.times { print it } 


A large number of methods are available for processing sequences to which closures can be applied:

 'qwerty'.each { print it } ('a'..'z').each { print it } ('a'..'z').findAll { el -> // = filter el in ['e', 'y', 'u', 'i', 'o', 'a'] }.each { print it + ' ' } (0..10).collect { el -> // = map el * 10 }.each { print it + ' ' } def sum = (0..10).inject(0) { prev, elem -> // = reduce return prev + elem } 


It is also not necessary to use the return keyword in closure. If the parameter name is not explicitly specified, then it is used by default.

Since closure is an object, nothing prevents it from returning from another closure, and thus creating higher-order functions:
 def cloA = {param -> def cloB = { return param * 10 } } def b = cloA(10) println b(10) 


Files



For directories there are functions eachFile and eachFileRecursive:

 new File('.').eachFile { println it } 

 ./.project ./src ./.settings ./.classpath ./bin 


For processing text files, the eachLine function:
 new File('textfile.txt').eachLine { println it } 


Writing to files is also very convenient:
 def pw = new File('textfile.txt').newPrintWriter() pw.println("new line") 


Classes


 class Account { String name BigDecimal value } //      //   -    // a = new Account() // a.setName("Account #1") // a.setValue(new BigDecimal(10)) a = new Account(name : "Account #1", value : new BigDecimal(10)) //      def name = a.getName() a.setName("Account #2") println "${a.name}" class Person { def first def last //    void setFirst(first) { println "${this.first} is becoming ${first}" this.first = first } } p = new Person(first : "A", last : "G") //    ,     p.first = "C" println "${p.first} ${p.last}" //    java class ExtendedAccount extends Account { def debt //   ExtendedAccount(name, value, debt) { setName(name) setValue(value) setDebt(debt) } def String toString() { "${name} ${value} ${debt}" } } //    "Could not find matching constructor for: ExtendedAccount()" //e = new ExtendedAccount() println new ExtendedAccount("A", new BigDecimal(10), 1) 


Immutable classes are set using the Immutable annotation:

 @Immutable class ImmutableClass { String a Integer b } def ic = new ImmutableClass(a : "a", b : 1) 


When using this annotation, you need to explicitly indicate what type of data the field is.

Operators



"?:" Elvis operator
 def b = a ?: "b" 

Checks the variable a, and if it is null or false, it takes the value specified next. Otherwise, the value of the variable a is taken.

"?." Safe navigation
Used to avoid NullPointerException error
 def user = Users.get("a") def posts = user?.posts println posts 

Returns null if user contains null instead of throwing a NullPointerException.

"*." Spread operator
Applies the specified method to all items in a collection. Equivalent to the following:
 parent*.action == parent.collect {ch -> child?.action} 


Example of use:
 def sizes = ['string', 'long string']*.size() println sizes 

 [6, 11] 


You can also use it to compile lists and dictionaries:
 def x = [2, 3] def y = [0, 1, *x, 4] println y def a = [3 : 'c', 4 : 'd'] def b = [1 : 'a', 2: 'b', * : a, 5 : 'e'] println b 

 [0, 1, 2, 3, 4] [1:a, 2:b, 3:c, 4:d, 5:e] 


In Groovy, you can overload the operators +, -, *, etc. To do this, you must define the appropriate method for the class. For example, to overload the ++ operator, you need to override the next () method:

 class RandomVal { //          private def value private Random randomGen = new Random() def next() { this.value = randomGen.nextInt() } RandomVal() { this.value = randomGen.nextInt() } def String toString() { "${this.value}" } } def r = new RandomVal() println(r) r++ println(r) 


The "==" operator is already overloaded for all objects - and calls the "isEquals ()" method. A full list of methods that need to be overridden for operator overloading is available here: http://groovy.codehaus.org/Operator+Overloading .

SQL



SQL queries are handled very simply:
 import groovy.sql.Sql def final ADDRESS = "jdbc:jtds:sqlserver://serverName/dbName" def final USERNAME = "username" def final PASSWD = "password" def final DRIVER = "net.sourceforge.jtds.jdbc.Driver" sql = Sql.newInstance(ADDRESS, USERNAME, PASSWD, DRIVER) sql.eachRow("select * from tableName") { el -> println "${el.id} -- ${el.firstName}" } def firstName = "A" def lastName = "G" sql.execute("insert into tableName (firstName, lastName) " + "values (${firstName}, ${lastName})") sql.execute("insert into tableName (firstName, lastName) " + "values (?, ?)", [firstName, lastName]) 


XML


There are builders in groovy that can be used to generate XML. For generation, an instance of the MarkupBuilder object is created, on which pseudo-methods are called — the name of this method and the parameters passed will be used to generate the tag:

 import groovy.xml.MarkupBuilder def mb = new MarkupBuilder() mb.html() { head() { title("This is the title") } body() { div("class" : "main") { p("this is the body") } } } 

Conclusion:
 <html> <head> <title>This is the title</title> </head> <body> <div class='main'> <p>this is the body</p> </div> </body> </html> 


As a parameter to the MarkupBuilder constructor, you can pass any PrintWriter:
 def fb = new MarkupBuilder(new File("index.html").newPrintWriter()) 


Parsing XML is also very simple:
 import groovy.xml.MarkupBuilder import java.io.StringWriter def sw = new StringWriter() def mb = new MarkupBuilder(sw) mb.html() { body() { div("class" : "main") { p("this is the body") } div() { p("this is the body 1") p("this is the body 2") p("this is the body 3") } } } def xml = sw.toString() println xml import groovy.util.XmlParser; def parser = new XmlParser() def doc = parser.parseText(xml) //def doc = parser.parse("index.html") println doc.body.div[1].p[1] //  Node println doc.body.div[1].p //  ,   Node println doc.body.div["@class"] //    class   div 


Conclusion:
 <html> <body> <div class='main'> <p>this is the body</p> </div> <div> <p>this is the body 1</p> <p>this is the body 2</p> <p>this is the body 3</p> </div> </body> </html> p[attributes={}; value=[this is the body 2]] [p[attributes={}; value=[this is the body 1]], p[attributes={}; value=[this is the body 2]], p[attributes={}; value=[this is the body 3]]] [main, null] 


Groovlets


Using the GroovyServlet class, it is possible to run Groovy scripts as servlets.
First of all, for this you need to add a few lines to web.xml:

 <servlet> <servlet-name>GroovyServlet</servlet-name> <servlet-class>groovy.servlet.GroovyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>GroovyServlet</servlet-name> <url-pattern>*.groovy</url-pattern> </servlet-mapping> 


Now all requests for .groovy files will be processed by the GroovyServlet class.
The following variables are already available for use in these scripts:

- request & response
- context, application, session
- out (= response.getWriter ())
- sout (= response.getOutputStream ())
- html (= new MarkupBuilder (out))

 html.html() { body() { div("class" : "main") { p("this is the body") } div() { p("this is the body 1") p("this is the body 2") p("this is the body 3") } } } 


Will give the browser a generated html page.

List of sources used:


Kenneth Barclay, John Savage "Groovy programming for an Java developers"
http://groovy.codehaus.org/

Source: https://habr.com/ru/post/122127/


All Articles