Groovy in 15 Minutes - An Overview
Groovy is an object-oriented programming language developed for the Java platform as an alternative to the Java language with the capabilities of Python, Ruby, and Smalltalk.
Groovy uses Java-like syntax with JVM dynamic compilation of bytecode 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
- Overloading operations
[ http://ru.wikipedia.org/wiki/Groovy ]
Moreover, almost always java code is valid groovy code.
To install, you need to download the archive from of. site , unzip it to a convenient place and add the environment variable GROOVY_HOME, and add the path to groovy / bin in 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 .
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"
You should not forget that all packaging types are immutable, so each time a calculation will create a new object.
1) Java Strings - strings in single quotes
2) Groovy Strings, they are GStrings - in ordinary quotes
You can insert parameters in groovy strings, you can’t insert parameters in ordinary strings
+ And * operations are applicable to strings
Also, ++ and - - apply to strings (since groovy supports operator overloading)
Groovy has a set of regular expressions at the level of language constructs:
Dictionaries (maps) and lists are also supported at the level of language constructs:
You can access list items in groovy as follows:
Range is the same object, so constructions like the latter are possible. Negative indexes, as in python, return elements from the end of the list.
Range can be composed of lines:
Moreover, range can be made from any object that has the next () and prev () methods.
The loops in groovy are exactly the same as in java, plus another “foreach” is added to them:
The return keyword is optional; by default, the value of the last mentioned variable in the function will be returned.
Closure is an anonymous function.
Many objects have methods for which closure is passed as parameters:
A large number of methods are available for processing sequences to which closures can be applied:
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 returning it from another closure, and thus create higher-order functions:
There are eachFile and eachFileRecursive functions for directories:
To process text files - eachLine function:
Writing to files is also very convenient:
Immutable classes are defined using annotations Immutable :
When using this annotation, you must explicitly indicate what type of data field.
"?:" Elvis operator
Checks the variable a, and if it is null or false, it takes the value indicated next. Otherwise, the value of the variable a is taken.
"?." Safe navigation
Used to avoid a NullPointerException error
Will return null if user contains null instead of throwing a NullPointerException.
"*." Spread operator
Applies the specified method to all elements of a collection. Equivalent to the following:
Usage example:
You can also use monjo to compile lists and dictionaries:
In Groovy, you can overload operators +, -, *, etc. To do this, you need to define the appropriate method for the class. For example, to overload the ++ operator, you need to override the next () method:
The operator "==" is already overloaded for all objects - and calls the "isEquals ()" method. A complete list of methods that must be overridden to overload operators is available here: http://groovy.codehaus.org/Operator+Overloading .
SQL queries are handled very simply:
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:
Conclusion:
You can pass any PrintWriter as a parameter to the MarkupBuilder constructor:
XML parsing is also very simple:
Conclusion:
Using the GroovyServlet class, it is possible to run scripts on Groovy as servlets.
First of all, for this you need to add a few lines to web.xml:
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))
It will give the browser the generated html page.
Kenneth Barclay, John Savage "Groovy programming: an introduction for Java developers"
http://groovy.codehaus.org/
Groovy uses Java-like syntax with JVM dynamic compilation of bytecode 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
- Overloading operations
[ http://ru.wikipedia.org/wiki/Groovy ]
Moreover, almost always java code is valid groovy code.
Installation
To install, you need to download the archive from of. site , unzip it to a convenient place and add the environment variable GROOVY_HOME, and add the path to groovy / bin in 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
You should not forget that all packaging types are immutable, so each time a calculation will create a new object.
Lines in Groovy
1) Java Strings - strings in single quotes
2) Groovy Strings, they are GStrings - in ordinary quotes
You can insert parameters in groovy strings, you can’t insert parameters in ordinary strings
javaString = 'java'
groovyString = "${javaString}"
j = '${javaString}'
bigGroovyString = """
${javaString}
${groovyString}
${j}
${2 + 2}
"""
println bigGroovyString
java
java
${javaString}
4
+ And * operations are applicable to strings
groovy:000> a = "a"
===> a
groovy:000> a + "123"
===> a123
groovy:000> a * 5
===> aaaaa
Also, ++ and - - apply to strings (since groovy supports operator overloading)
groovy:000> a = 'abc'
===> abc
groovy:000> a++
===> abd
groovy:000> a--
===> abс
Groovy has a set of 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
Dictionaries (maps) and lists are also supported at the level of language constructs:
groovy:000> a = [1, 3, 5]
===> [1, 3, 5]
groovy:000> b = [1: true, 0: false]
===> {1=true, 0=false}
Ranges
You can access 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 constructions like the latter are possible. Negative indexes, as in python, return elements from the end of the list.
Range can be composed of lines:
groovy:000> 'a'..'aa'
===> a..aa
Moreover, range can be made from any object that has the next () and prev () methods.
Cycles
The loops 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 mentioned 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 for which closure is passed as parameters:
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 returning it from another closure, and thus create higher-order functions:
def cloA = {param ->
def cloB = {
return param * 10
}
}
def b = cloA(10)
println b(10)
Files
There are eachFile and eachFileRecursive functions for directories:
new File('.').eachFile {
println it
}
./.project
./src
./.settings
./.classpath
./bin
To process text files - 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 defined using annotations Immutable :
@Immutable
class ImmutableClass {
String a
Integer b
}
def ic = new ImmutableClass(a : "a", b : 1)
When using this annotation, you must explicitly indicate what type of data field.
Operators
"?:" Elvis operator
def b = a ?: "b"
Checks the variable a, and if it is null or false, it takes the value indicated next. Otherwise, the value of the variable a is taken.
"?." Safe navigation
Used to avoid a NullPointerException error
def user = Users.get("a")
def posts = user?.posts
println posts
Will return null if user contains null instead of throwing a NullPointerException.
"*." Spread operator
Applies the specified method to all elements of a collection. Equivalent to the following:
parent*.action == parent.collect {ch -> child?.action}
Usage example:
def sizes = ['string', 'long string']*.size()
println sizes
[6, 11]
You can also use monjo 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 operators +, -, *, etc. To do this, you need to 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 complete list of methods that must be overridden to overload operators 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:
This is the title this is the body
You can pass any PrintWriter as a parameter to the MarkupBuilder constructor:
def fb = new MarkupBuilder(new File("index.html").newPrintWriter())
XML parsing 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:
this is the body
this is the body 1
this is the body 2
this is the body 3
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 scripts on Groovy as servlets.
First of all, for this you need to add a few lines to web.xml:
GroovyServlet groovy.servlet.GroovyServlet GroovyServlet *.groovy 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")
}
}
}
It will give the browser the generated html page.
List of sources used:
Kenneth Barclay, John Savage "Groovy programming: an introduction for Java developers"
http://groovy.codehaus.org/