头发为什么长不长| 双鱼座的幸运色是什么颜色| 斑是什么原因造成的| 冒菜和麻辣烫有什么区别| 肺实性结节是什么意思| 鼻子有臭味是什么原因| 手机账号是什么| 卵泡刺激素高说明什么| 血红蛋白浓度偏低是什么原因| 结论是什么意思| 外阴炎是什么原因引起的| 菌群异常是什么意思| 阴帝是什么| qrs波代表什么| 眼睛为什么会散光| 粤菜是什么口味| 芫荽是什么| 不着相是什么意思| 天蝎座的幸运色是什么| 雅号是什么意思| 哺乳期感冒吃什么药不影响哺乳| 泡鲁达是什么| 夏天适合养什么花| 有什么症状| 什么是豆制品| 帛书是什么意思| 过堂是什么意思| 嘴角起痘是什么原因| 牛肉用什么调料| 膈应是什么意思| 鼻孔干燥是什么原因| 521是什么星座的| 肝虚火旺吃什么中成药| 吊丝是什么意思| 总放屁是什么原因| 气血是什么意思| 蚂蚁代表什么生肖| 苏州有什么好玩的| 球蛋白偏高是什么原因| 什么红什么绿| 女人身体弱带什么辟邪| 总是什么意思| 松子吃了有什么好处和坏处| 取模是什么意思| 复读是什么意思| 吃鸡蛋胃疼是什么原因| 五毛是什么意思| 敏感的反义词是什么| 肠粘连吃什么药| 宫颈病变有什么症状| 五福临门是什么生肖| 甲状腺球蛋白抗体高是什么意思| 阴唇痒用什么药| 情感障碍是什么意思| 鸡汤放什么调料| 吃什么能提高免疫力| 肺气肿是什么病| 吃什么补眼睛| 重庆沱茶属于什么茶| 小孩割包皮挂什么科室| 医院归什么部门管理| bmi是什么意思啊| 祛湿有什么好处| 违和感是什么意思| 海葡萄是什么| 耳鸣吃什么药比较好| 儿童水杯什么材质好| 喊6个1是什么意思| 反法西斯是什么意思| 破伤风疫苗什么时候打| 背债是什么意思| 血液为什么是红色| 梦见捡到钱是什么征兆| 喜讯是什么意思| 胆囊炎的症状是什么| 桑叶长什么样子图片| 膝盖缝里面疼什么原因| 甲减吃什么药| 女人骨质疏松吃什么最好| 喝酒会得什么病| 什么首什么胸| 金骏眉属于什么茶| 吐司是什么意思| 下午四点多是什么时辰| 儿童感冒挂什么科| 法尔如是是什么意思| 农历五月初五是什么节日| 肾主骨是什么意思| 谷草转氨酶偏高是什么意思| 什么的铅笔| 叔叔老婆叫什么| 岩茶是什么茶类| 苹果枸杞红枣煮水喝有什么功效| 猫对什么颜色感兴趣| 628是什么星座| 卧轨是什么意思| 尿道痛什么原因| 跖疣是什么| 清洁度二度是什么意思| 经常吃海带有什么好处和坏处| 摩卡是什么意思| 宝贝是什么意思| 限高什么意思| 把妹什么意思| 梦见吃饭是什么意思| 边缘性人格障碍是什么| 口腔溃疡看什么科| 烧仙草粉是什么做的| 感冒扁桃体发炎吃什么药| esse是什么牌子的烟| 看耳朵挂什么科| 乳腺增生不能吃什么食物| 川芎有什么功效与作用| 盐和小苏打一起有什么作用| 打蛋器什么牌子好| 皮肤瘙痒用什么药膏| 去香港澳门旅游需要准备什么| 金牛座什么性格| 名什么古什么| 怀孕初期分泌物是什么样的| 地球代表什么生肖| 卡介疫苗什么时候打| 什么天空填动词| 中指戴戒指代表什么| 杨贵妃是什么生肖| 龟头瘙痒用什么药膏| 黄色配什么颜色| 嫂夫人什么意思| 淋巴细胞比率偏高是什么原因| 鹦鹉吃什么食物最好| 痣长在什么地方不好| 无名指是什么经络| 叶酸每天什么时候吃最好| 多多益善是什么意思| 生理盐水和食用盐水有什么区别| 猪肝可以钓什么鱼| 梦见很多苍蝇是什么意思| 女性尿路感染什么原因引起的| 什么的小手| 泡菜生花用什么方法可以去掉| 姑息性化疗什么意思| 什么发抖| 口苦口臭口干吃什么药| 什么情况下要打破伤风针| 电影监制是做什么的| 人突然晕倒是什么原因引起的| 什么身什么骨| 为什么要喝酒| 花名册是什么意思| 电音是什么意思| 什么原因造成耳鸣| 白肺是什么| 淋巴结节吃什么药最好| 脾虚是什么原因引起的| 呵呵的含义是什么意思| 增加胃动力最好的药是什么药| 什么茶解酒| 手指腱鞘炎是什么原因造成的| 阴道口瘙痒是什么原因| 钮钴禄什么意思| 属相牛和什么属相配| 喝茶什么意思| 九二年属猴的是什么命| 运动后喝什么水最好| 1119是什么星座| 一个月一个泉是什么字| 经常抠鼻子有什么危害| 人参和什么泡酒能壮阳| 富二代是什么意思| 肺炎支原体感染吃什么药| 口腔发苦是什么原因| 弱精吃什么能提高活力| 西洋参跟花旗参有什么区别| 马首是瞻是什么生肖| 血管瘤挂什么科比较好| 海豚吃什么食物| 皮肤黄吃什么可以改善| 女人脾虚吃什么药最好| 谈恋爱是为了什么| 为什么发动文化大革命| 插入阴道是什么感觉| 宫颈管分离什么意思| 煲蛇汤放什么材料好| tags是什么意思| 龙冲什么生肖| 胆囊壁厚是什么意思| 罗文和甄妮什么关系| 吃避孕药有什么好处| 立加羽念什么| 三季人是什么意思| 五十而知天命是什么意思| 24k是什么意思| 什么是血脂| 葡萄糖升高说明什么| dr和ct有什么区别| 梦见自己抬棺材是什么意思| 一什么冰雹| 焦虑症用什么药好| 少田宅痣是什么意思| 胃底腺息肉是什么意思| 支原体肺炎用什么药| 免疫力和抵抗力有什么区别| 九月29号是什么星座| 美容行业五行属什么| 7月24日是什么星座| 上吐下泻是什么原因| 给老师送花送什么花合适| 什么是组织| 心三联是指什么| 生姜和红糖熬水有什么作用| 授人以鱼不如授人以渔什么意思| hbeag阳性是什么意思| 小米配什么熬粥最好| 尿特别黄是什么原因| 美妙绝伦是什么意思| 甲骨文是写在什么上面的| 常态是什么意思| 一个火一个丙念什么| 橡木色是什么颜色| 为什么要打肝素| 女生喜欢吃酸说明什么| 正月十九是什么日子| 成人改名字需要什么手续| 补充b族维生素有什么好处| 胳膊出汗是什么原因| 为什么会呼吸性碱中毒| 毒龙什么意思| 子宫肌瘤有什么症状| 鼻孔干燥是什么原因| 隐翅虫是什么| 什么样的手相最有福气| 配裙子穿什么鞋子好看| 高风亮节是什么意思| 纯化水是什么水| 肠胃不好吃什么药好| 大姨妈来了两天就没了什么原因| 吃什么水果对嗓子好| 戾气什么意思| 凤凰单丛属于什么茶| 女生的胸长什么样子| 鲫鱼不能和什么一起吃| 红细胞偏低有什么危害| 书犹药也下一句是什么| 令堂是什么意思| 今年21岁属什么生肖| 头孢加酒有什么反应| 火头鱼是什么鱼| 这句话是什么意思| 肠粉为什么叫肠粉| 滑精是什么意思| 身份证后四位代表什么| aquascutum是什么牌子| 外阴炎是什么原因引起的| w3是什么意思| 一什么金鱼| 屋漏偏逢连夜雨是什么意思| 工装裤搭配什么鞋子| 手背麻木是什么原因| 扁桃体发炎咳嗽吃什么药效果好| 治疗勃起困难有什么药| 婴儿呛奶是什么原因引起的| 先天性是什么意思| 丹凤朝阳什么意思| 胃胀气适合吃什么食物| 百度Jump to content

水印之美:传统艺术的赓续与焕新

From Wikipedia, the free encyclopedia
Groovy
Groovy Logo
ParadigmMulti-paradigm: object-oriented, imperative, functional, aspect-oriented, scripting
Designed byJames Strachan
DeveloperPaul King (PMC Chair)
Jochen Theodorou (Tech Lead)
Guillaume Laforge
Cedric Champeau
Daniel Sun
Eric Milles
First appeared2003; 22 years ago (2003)
Stable release4.0.27[1] Edit this on Wikidata (24 May 2025; 2 months ago (24 May 2025)) [±]
Typing disciplineDynamic, static, strong, duck
PlatformJava SE
LicenseApache License 2.0
Filename extensions.groovy, .gvy, .gy, .gsh[2]
Websitegroovy-lang.org Edit this at Wikidata
Major implementations
Gradle, Grails
Influenced by
Java, Python, Ruby, Smalltalk, Perl
Influenced
Kotlin
百度   周普国在总结时强调,要围绕总体思路,狠抓落实。

Apache Groovy is a Java-syntax-compatible object-oriented programming language for the Java platform. It is both a static and dynamic language with features similar to those of Python, Ruby, and Smalltalk. It can be used as both a programming language and a scripting language for the Java Platform, is compiled to Java virtual machine (JVM) bytecode, and interoperates seamlessly with other Java code and libraries. Groovy uses a curly-bracket syntax similar to Java's. Groovy supports closures, multiline strings, and expressions embedded in strings. Much of Groovy's power lies in its AST transformations, triggered through annotations.

Groovy 1.0 was released on January 2, 2007, and Groovy 2.0 in July, 2012. Since version 2, Groovy can be compiled statically, offering type inference and performance near that of Java.[3][4] Groovy 2.4 was the last major release under Pivotal Software's sponsorship which ended in March 2015.[5] Groovy has since changed its governance structure to a Project Management Committee in the Apache Software Foundation.[6]

History

[edit]

James Strachan first talked about the development of Groovy on his blog in August 2003.[7] In March 2004, Groovy was submitted to the Java Community Process (JCP) as JSR 241[8] and accepted by ballot. Several versions were released between 2004 and 2006. After the JCP standardization effort began, the version numbering changed, and a version called "1.0" was released on January 2, 2007. After various betas and release candidates numbered 1.1, on December 7, 2007, Groovy 1.1 Final was released and immediately renumbered as Groovy 1.5 to reflect the many changes made.

In 2007, Groovy won the first prize at JAX 2007 innovation award.[9] In 2008, Grails, a Groovy web framework, won the second prize at JAX 2008 innovation award.[10]

In November 2008, SpringSource acquired the Groovy and Grails company (G2One).[11] In August 2009 VMware acquired SpringSource.[12]

In April 2012, after eight years of inactivity, the Spec Lead changed the status of JSR 241 to dormant.[8]

Strachan had left the project silently a year before the Groovy 1.0 release in 2007.[citation needed] In Oct 2016, Strachan stated "I still love groovy (jenkins pipelines are so groovy!), java, go, typescript and kotlin".[13]

On July 2, 2012, Groovy 2.0 was released, which, among other new features, added static compiling and static type checking.

When the Pivotal Software joint venture was spun-off by EMC Corporation (EMC) and VMware in April 2013, Groovy and Grails formed part of its product portfolio. Pivotal ceased sponsoring Groovy and Grails from April 2015.[5] That same month, Groovy changed its governance structure from a Codehaus repository to a Project Management Committee (PMC) in the Apache Software Foundation via its incubator.[6] Groovy graduated from Apache's incubator and became a top-level project in November 2015.[14]

On February 7, 2020, Groovy 3.0 was released.[15] Version 4.0 was released on January 25, 2022.[16]

Features

[edit]

Most valid Java files are also valid Groovy files. Although the two languages are similar, Groovy code can be more compact, because it does not need all the elements that Java needs.[17] This makes it possible for Java programmers to learn Groovy gradually by starting with familiar Java syntax before acquiring more Groovy programming idioms.[18]

Groovy features not available in Java include both static and dynamic typing (with the keyword def), operator overloading, native syntax for lists and associative arrays (maps), native support for regular expressions, polymorphic iteration, string interpolation, added helper methods, and the safe navigation operator ?. to check automatically for null pointers (for example, variable?.method(), or variable?.field).[19]

Since version 2, Groovy also supports modularity (shipping only the jars that the project uses, thus reducing the size of Groovy's library), type checking, static compilation, Project Coin syntax enhancements, multicatch blocks and ongoing performance enhancements using the invokedynamic instruction introduced in Java 7.[20]

Groovy natively supports markup languages such as XML and HTML by using an inline Document Object Model (DOM) syntax. This feature enables the definition and manipulation of many types of heterogeneous data assets with a uniform and concise syntax and programming methodology.[citation needed]

Unlike Java, a Groovy source code file can be executed as an (uncompiled) script, if it contains code outside any class definition, if it is a class with a main method, or if it is a Runnable or GroovyTestCase. A Groovy script is fully parsed, compiled, and generated before executing (similar to Python and Ruby). This occurs under the hood, and the compiled version is not saved as an artifact of the process.[21]

GroovyBeans, properties

[edit]

GroovyBeans are Groovy's version of JavaBeans. Groovy implicitly generates getters and setters. In the following code, setColor(String color) and getColor() are implicitly generated. The last two lines, which appear to access color directly, are actually calling the implicitly generated methods.[22]

class AGroovyBean {
  String color
}

def myGroovyBean = new AGroovyBean()

myGroovyBean.setColor('baby blue')
assert myGroovyBean.getColor() == 'baby blue'

myGroovyBean.color = 'pewter'
assert myGroovyBean.color == 'pewter'

Groovy offers simple, consistent syntax for handling lists and maps, reminiscent of Java's array syntax.[23]

def movieList = ['Dersu Uzala', 'Ran', 'Seven Samurai']  // Looks like an array, but is a list
assert movieList[2] == 'Seven Samurai'
movieList[3] = 'Casablanca'  // Adds an element to the list
assert movieList.size() == 4

def monthMap = [ 'January' : 31, 'February' : 28, 'March' : 31 ]  // Declares a map
assert monthMap['March'] == 31  // Accesses an entry
monthMap['April'] = 30  // Adds an entry to the map
assert monthMap.size() == 4

Prototype extension

[edit]

Groovy offers support for prototype extension through ExpandoMetaClass, Extension Modules (only in Groovy 2), Objective-C-like Categories and DelegatingMetaClass.[24]

ExpandoMetaClass offers a domain-specific language (DSL) to express the changes in the class easily, similar to Ruby's open class concept:

Number.metaClass {
  sqrt = { Math.sqrt(delegate) }
}

assert 9.sqrt() == 3
assert 4.sqrt() == 2

Groovy's changes in code through prototyping are not visible in Java, since each attribute/method invocation in Groovy goes through the metaclass registry. The changed code can only be accessed from Java by going to the metaclass registry.

Groovy also allows overriding methods as getProperty(), propertyMissing() among others, enabling the developer to intercept calls to an object and specify an action for them, in a simplified aspect-oriented way. The following code enables the class java.lang.String to respond to the hex property:

enum Color {
  BLACK('#000000'), WHITE('#FFFFFF'), RED('#FF0000'), BLUE('#0000FF')
  String hex
  Color(String hex) { 
    this.hex = hex 
  }
}

String.metaClass.getProperty = { String property ->
  def stringColor = delegate
  if (property == 'hex') {
    Color.values().find { it.name().equalsIgnoreCase stringColor }?.hex
  }
}

assert "WHITE".hex == "#FFFFFF"
assert "BLUE".hex == "#0000FF"
assert "BLACK".hex == "#000000"
assert "GREEN".hex == null

The Grails framework uses metaprogramming extensively to enable GORM dynamic finders, like User.findByName('Josh') and others.[25]

Dot and parentheses

[edit]

Groovy's syntax permits omitting parentheses and dots in some situations. The following groovy code

take(coffee).with(sugar, milk).and(liquor)

can be written as

take coffee with sugar, milk and liquor

enabling the development of domain-specific languages (DSLs) that look like plain English.

Functional programming

[edit]

Although Groovy is mostly an object-oriented language, it also offers functional programming features.

Closures

[edit]

According to Groovy's documentation: "Closures in Groovy work similar to a 'method pointer', enabling code to be written and run in a later point in time".[26] Groovy's closures support free variables, i.e. variables that have not been explicitly passed as a parameter to it, but exist in its declaration context, partial application (that it terms 'currying'[27]), delegation, implicit, typed and untyped parameters.

When working on Collections of a determined type, the closure passed to an operation on the collection can be inferred:

list = [1, 2, 3, 4, 5, 6, 7, 8, 9]

/* 
 * Non-zero numbers are coerced to true, so when it % 2 == 0 (even), it is false.
 * The type of the implicit "it" parameter can be inferred as an Integer by the IDE.
 * It could also be written as:
 * list.findAll { Integer i -> i % 2 }
 * list.findAll { i -> i % 2 }
 */
def odds = list.findAll { it % 2 }

assert odds == [1, 3, 5, 7, 9]

A group of expressions can be written in a closure block without reference to an implementation and the responding object can be assigned at a later point using delegation:

// This block of code contains expressions without reference to an implementation
def operations = {
  declare 5
  sum 4
  divide 3
  print
}
/* 
 * This class will handle the operations that can be used in the closure above. Another class
 * could be declared having the same methods, but using, for example, webservice operations
 * in the calculations.
 */
class Expression {
  BigDecimal value

  /* 
   * Though an Integer is passed as a parameter, it is coerced into a BigDecimal, as was 
   * defined. If the class had a 'declare(Integer value)' method, it would be used instead.
   */
  def declare(BigDecimal value) {
    this.value = value
  }
  
  def sum(BigDecimal valueToAdd) {
    this.value += valueToAdd
  }
  
  def divide(BigDecimal divisor) {
    this.value /= divisor
  }
  
  def propertyMissing(String property) {
    if (property == "print") println value
  }
}
// Here is defined who is going to respond the expressions in the block of code above.
operations.delegate = new Expression()
operations()

Curry

[edit]

Usually called partial application,[27] this Groovy feature allows closures' parameters to be set to a default parameter in any of their arguments, creating a new closure with the bound value. Supplying one argument to the curry() method will fix argument one. Supplying N arguments will fix arguments 1 .. N.

def joinTwoWordsWithSymbol = { symbol, first, second -> first + symbol + second }
assert joinTwoWordsWithSymbol('#', 'Hello', 'World') == 'Hello#World'

def concatWords = joinTwoWordsWithSymbol.curry(' ')
assert concatWords('Hello', 'World') == 'Hello World'

def prependHello = concatWords.curry('Hello')
//def prependHello = joinTwoWordsWithSymbol.curry(' ', 'Hello')
assert prependHello('World') == 'Hello World'

Curry can also be used in the reverse direction (fixing the last N arguments) using rcurry().

def power = { BigDecimal value, BigDecimal power ->
  value**power
}

def square = power.rcurry(2)
def cube = power.rcurry(3)

assert power(2, 2) == 4
assert square(4) == 16
assert cube(3) == 27

Groovy also supports lazy evaluation,[28][29] reduce/fold,[30] infinite structures and immutability,[31] among others.[32]

JSON and XML processing

[edit]

On JavaScript Object Notation (JSON) and XML processing, Groovy employs the Builder pattern, making the production of the data structure less verbose. For example, the following XML:

<languages>
  <language year="1995">
    <name>Java</name>
    <paradigm>object oriented</paradigm>
    <typing>static</typing>
  </language>
  <language year="1995">
    <name>Ruby</name>
    <paradigm>functional, object oriented</paradigm>
    <typing>duck typing, dynamic</typing>
  </language>
  <language year="2003">
    <name>Groovy</name>
    <paradigm>functional, object oriented</paradigm>
    <typing>duck typing, dynamic, static</typing>
  </language>
</languages>

can be generated via the following Groovy code:

def writer = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(writer)
builder.languages {
  language(year: 1995) {
    name "Java"
    paradigm "object oriented"
    typing "static"
  }
  language (year: 1995) {
    name "Ruby"
    paradigm "functional, object oriented"
    typing "duck typing, dynamic"
  }
  language (year: 2003) {
    name "Groovy"
    paradigm "functional, object oriented"
    typing "duck typing, dynamic, static"
  }
}

and also can be processed in a streaming way through StreamingMarkupBuilder. To change the implementation to JSON, the MarkupBuilder can be swapped to JsonBuilder.[33]

To parse it and search for a functional language, Groovy's findAll method can serve:

def languages = new XmlSlurper().parseText writer.toString()

// Here is employed Groovy's regex syntax for a matcher (=~) that will be coerced to a 
// boolean value: either true, if the value contains our string, or false otherwise.
def functional = languages.language.findAll { it.paradigm =~ "functional" }
assert functional.collect { it.name } == ["Groovy", "Ruby"]

String interpolation

[edit]

In Groovy, strings can be interpolated with variables and expressions by using GStrings:[34]

BigDecimal account = 10.0
def text = "The account shows currently a balance of $account"
assert text == "The account shows currently a balance of 10.0"

GStrings containing variables and expressions must be declared using double quotes.

A complex expression must be enclosed in curly brackets. This prevents parts of it from being interpreted as belonging to the surrounding string instead of to the expression:

BigDecimal minus = 4.0
text = "The account shows currently a balance of ${account - minus}"
assert text == "The account shows currently a balance of 6.0"

// Without the brackets to isolate the expression, this would result:
text = "The account shows currently a balance of $account - minus"
assert text == "The account shows currently a balance of 10.0 - minus"

Expression evaluation can be deferred by employing arrow syntax:

BigDecimal tax = 0.15
text = "The account shows currently a balance of ${->account - account*tax}"
tax = 0.10

// The tax value was changed AFTER declaration of the GString. The expression 
// variables are bound only when the expression must actually be evaluated:
assert text == "The account shows currently a balance of 9.000"

Abstract syntax tree transformation

[edit]

According to Groovy's own documentation, "When the Groovy compiler compiles Groovy scripts and classes, at some point in the process, the source code will end up being represented in memory in the form of a Concrete Syntax Tree, then transformed into an Abstract Syntax Tree. The purpose of AST Transformations is to let developers hook into the compilation process to be able to modify the AST before it is turned into bytecode that will be run by the JVM. AST Transformations provides Groovy with improved compile-time metaprogramming capabilities allowing powerful flexibility at the language level, without a runtime performance penalty."[35]

Examples of ASTs in Groovy are:

  • Category and Mixin transformation
  • Immutable AST Macro
  • Newify transformation
  • Singleton transformation

among others.

The testing framework Spock uses AST transformations to allow the programmer to write tests in a syntax not supported by Groovy, but the relevant code is then manipulated in the AST to valid code.[36] An example of such a test is:

def "maximum of #a and #b is #c" () {
  expect:
  Math.max (a, b) == c

  where:
  a | b || c
  3 | 5 || 5
  7 | 0 || 7
  0 | 0 || 0
}

Traits

[edit]

According to Groovy's documentation, "Traits are a structural construct of the language that allows: composition of behaviors, runtime implementation of interfaces, behavior overriding, and compatibility with static type checking/compilation."

Traits can be seen as interfaces carrying both default implementations and state. A trait is defined using the trait keyword:

trait FlyingAbility { /* declaration of a trait */
  String fly() { "I'm flying!" } /* declaration of a method inside a trait */
}

Then, it can be used like a normal interface using the keyword implements:

class Bird implements FlyingAbility {} /* Adds the trait FlyingAbility to the Bird class capabilities */
def bird = new Bird() /* instantiate a new Bird */
assert bird.fly() == "I'm flying!" /* the Bird class automatically gets the behavior of the FlyingAbility trait */

Traits allow a wide range of abilities, from simple composition to testing.

Adoption

[edit]

Notable examples of Groovy adoption include:

IDE support

[edit]

Many integrated development environments (IDEs) and text editors support Groovy:

Dialects

[edit]

There is one alternative implementation of Groovy:

  • Grooscript converts Groovy code to JavaScript code.[46] Although Grooscript has some limitations compared to Apache Groovy, it can use domain classes in both the server and the client.[47] Plugin support for Grails version 3.0 is provided, as well as online code conversions.[48]

See also

[edit]

References

[edit]

Citations

[edit]
  1. ^ "Release 4.0.27". 24 May 2025. Retrieved 25 May 2025.
  2. ^ "Groovy Goodness: Default Groovy Script File Extensions".
  3. ^ "Groovy 2.0 Performance compared to Java". 25 Aug 2012.
  4. ^ "Java vs Groovy2.0 vs Scala Simple Performance Test". 10 Jul 2012. Archived from the original on 10 December 2012. Retrieved 7 October 2012.
  5. ^ a b "Groovy 2.4 And Grails 3.0 To Be Last Major Releases Under Pivotal Sponsorship". 19 Jan 2015.
  6. ^ a b "Groovy joins Apache Incubator". 11 Mar 2015.
  7. ^ James Strachan (29 Aug 2003). "Groovy - the birth of a new dynamic language for the Java platform". Archived from the original on 1 September 2003.
  8. ^ a b "Java Community Process JSR 241".
  9. ^ "Groovy wins first prize at JAX 2007 innovation award". 2025-08-07. Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  10. ^ "They say a lot can happen over a cup of coffee". Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  11. ^ "SpringSource Acquires Groovy and Grails company (G2One)". 11 Nov 2008.
  12. ^ "VMWare Acquires SpringSource". 10 Aug 2009.
  13. ^ "Tweet from James Strachan". November 24, 2016. Retrieved 2025-08-07.
  14. ^ "Announcement on dev mailing list".
  15. ^ "Release GROOVY_3_0_0 · apache/groovy". GitHub. Retrieved 2025-08-07.
  16. ^ "Release GROOVY_4_0_0 · apache/groovy". GitHub. Retrieved 2025-08-07.
  17. ^ K?nig 2007, pg. 32
  18. ^ "Groovy style and language feature guidelines for Java developers". Groovy.codehaus.org. Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  19. ^ "Groovy – Differences from Java". Groovy.codehaus.org. Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  20. ^ "What's new in Groovy 2.0?". 28 Jun 2012.
  21. ^ K?nig 2007, pp. 37-8
  22. ^ K?nig 2007, pp. 38-9
  23. ^ K?nig 2007, pp. 41-3
  24. ^ "JN3525-MetaClasses". Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  25. ^ "Metaprogramming Techniques in Groovy and Grails". 11 Jun 2009.
  26. ^ "Groovy - Closures". Archived from the original on 2025-08-07.
  27. ^ a b "Does groovy call partial application 'currying'", 10 Aug 2013
  28. ^ "Groovy - Lazy Transformation". Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  29. ^ "Side Notes: Lazy lists in Groovy". 3 Feb 2011.
  30. ^ "Groovy's Fold". 20 Jun 2011. Archived from the original on 13 February 2015. Retrieved 12 February 2015.
  31. ^ "Functional Programming with Groovy". 5 Nov 2011.
  32. ^ "Function programming in Groovy". Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  33. ^ "JsonBuilder". Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  34. ^ "Groovy Strings - Different ways of creating them". 26 Dec 2009.
  35. ^ "Compile-time Metaprogramming - AST Transformations". Archived from the original on 2025-08-07. Retrieved 2025-08-07.
  36. ^ King, Paul (2020). "A History of the Groovy Programming Language". Proc. ACM Program. Lang. 4: 53. doi:10.1145/3386326.
  37. ^ "Groovy DSL for OFBiz business logic". Apache OFBiz Project Open Wiki.
  38. ^ "Simple-methods examples using Groovy". Apache OFBiz Project Open Wiki.
  39. ^ "Grails at LinkedIn". Retrieved 2025-08-07.
  40. ^ "Jenkins Pipeline".
  41. ^ Rocher, Graeme (October 2, 2008). "Graeme Rocher's Blog: Sky.com relaunches written in Grails". Graeme Rocher's Blog. Retrieved 2025-08-07.
  42. ^ Security Analysis of Emerging Smart Home Applications
  43. ^ "Scripting and the Script Library | Scripting & Properties". www.soapui.org. Retrieved 2025-08-07.
  44. ^ "Wired.Com" (PDF). www.springsource.org. Retrieved 2025-08-07.
  45. ^ "XWiki SAS" (PDF). www.springsource.org. Retrieved 2025-08-07.
  46. ^ "Grooscript Documentation". 12 Sep 2016. Archived from the original on 28 June 2017. Retrieved 4 July 2017.
  47. ^ "Presentation at SpringOne/2GX on Grooscript". 13 Dec 2015.
  48. ^ "Grooscript online conversions". 15 May 2017. Archived from the original on 9 July 2017. Retrieved 4 July 2017.

Sources

[edit]
[edit]
手脱皮是什么原因引起的 福生无量天尊什么意思 玻璃瓶属于什么垃圾 闻所未闻是什么意思 包虫病是什么症状
农历9月17日是什么星座 便秘吃什么能马上排便 三克油是什么意思 6.13是什么星座 大牛是什么意思
什么样的西瓜 dpl是什么意思 美商是什么意思 释迦摩尼是什么意思 黑色的裤子配什么颜色的上衣
风寒感冒流鼻涕吃什么药 扁扁的鱼叫什么鱼 容易流鼻血是什么原因 跌跌撞撞什么意思 尿液有泡沫是什么原因
什么山hcv9jop4ns7r.cn 未免是什么意思hcv7jop4ns7r.cn 做梦梦见蛇是什么征兆hcv8jop7ns4r.cn 序曲是什么意思hcv7jop7ns2r.cn 玉露茶属于什么茶hcv7jop5ns3r.cn
膜性肾病什么意思hcv7jop5ns2r.cn 考护士证需要什么条件hcv9jop0ns7r.cn 挚友什么意思hcv9jop3ns0r.cn 小孩晚上睡觉发梦癫什么原因hcv7jop7ns4r.cn 肛裂是什么原因引起的hcv8jop1ns0r.cn
1997年属什么生肖hcv9jop6ns6r.cn 宫缩是什么意思yanzhenzixun.com vodka是什么酒hcv9jop1ns0r.cn 右手大拇指抖动是什么原因hcv8jop7ns1r.cn 老掉头发是什么原因hcv8jop5ns6r.cn
脾阴虚吃什么中成药hcv8jop2ns4r.cn 胆固醇高吃什么最好1949doufunao.com 骨骼肌是什么意思hcv9jop2ns7r.cn 柠檬水什么时候喝最好hcv9jop6ns2r.cn 收尾是什么意思hcv9jop5ns2r.cn
百度