第4章 Java和Groovy集成
Groovy最大的賣點之一是它與Java的無縫集成。在本章中,我們將以各種方式探討這種集成。我們將使用普通的舊Groovy對象(POGOs)作為普通舊Java對象(pojo)的完全替代。我們將從Java調(diào)用Groovy代碼,從Groovy調(diào)用Java代碼。最后,我們將探索如何使用Ant來編譯整個項目,包括Groovy和Java類的健康組合。
4.1 Groovy的對象
package org.davisworld.bookstore
class Book{
String title
String author
Integer pages
}
正如我們在第16頁的1.1節(jié)Groovy中所看到的,這就是POGO的全部內(nèi)容。 Groovy將JavaBeans歸結(jié)為純粹的本質(zhì)。
Packaging(打包)
在此示例中,您會注意到的第一件事是包裝。 您可能永遠不需要打包Groovy腳本,但是Groovy類的打包方式與Java類的打包方式相同。 (有關(guān)編寫Groovy腳本的更多信息,請參見第86頁的命令行中的第5章,Groovy。)在Java開發(fā)人員看來,唯一看起來奇怪的是缺少分號。 (正如我們在第42頁的3.2節(jié),可選分號中所討論的,您可以根據(jù)需要將其重新添加。)
Public Classes, Private Attributes, Public Methods
// in Groovy:
class Book{
String title
String toString(){
return title
}
}
// in Java:
public class Book{
private String title;
public String toString(){
return title;
}
}
如果您未提供訪問修飾符(公共,私有或受保護的),則Groovy中的類隱式是公共的
。 在Java中,如果不另行說明,則類是包私有的
。 如果您在兩種語言之間來回移動時不注意,這可能是一個嚴重的“陷阱”。 (有關(guān)更多信息,請參見下頁的側(cè)欄。)
如果您不提供訪問修飾符,則Groovy中的屬性將隱式私有
。 您可以通過一些內(nèi)省來證明這一點:
println Book.getDeclaredField("title")
===> private java.lang.String Book.title
Groovy中的方法默認情況下是公共的
。 這是證明:
println Book.getDeclaredMethod("toString")
===> public java.lang.String Book.toString()
那么,Groovy開發(fā)人員對包私有訪問有什么反對意見呢?沒什么,真的。他們的目標是默認允許類做正確的事情,而包私有訪問是一個不幸的附帶損害。
花一分鐘想想你最近從事的主要Java項目。您有多少帶有私有屬性的公共POJOs? 在這里,您可能可以在此處安全地使用“ 80/20規(guī)則”,但是如果我按了您的要求,則最終可能會達到90%或更高。帶有私有屬性的公共類是編寫的絕大多數(shù)Java代碼,Groovy的智能默認設(shè)置反映了這一業(yè)務(wù)現(xiàn)實。
::: alert-info
Gotcha: No Package-Private Visibility(陷阱:沒有包私有可見性)
在Java中,如果將訪問修飾符保留在類,屬性或方法之外,則意味著同一包中的其他類或另一個包中的直接子類可以直接訪問它們。 這稱為包私有訪問。在Groovy中,沒有訪問修飾符的類被視為公共類。 沒有訪問修飾符的屬性被視為私有。 沒有訪問修飾符的方法是公共的。 盡管可以說這種快捷方式對于主流用法更為有用,但是它代表了Java語義不同于Groovy語義的少數(shù)情況之一。
在Groovy中,無法為類,屬性或方法包提供包私有
的可見性。 在Groovy中聲明公共,私有和受保護元素的方式與在Java中聲明方式相同。
?. http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html
:::
4.2 自動生成的Getter和Setter
class Book{
String title
}
Book book = new Book()
book.setTitle("Groovy Recipes")
println book.getTitle()
===> Groovy Recipes
盡管沒有如此明顯的public和private修飾符會稍微減少類的大小,但是真正自動產(chǎn)生getter和setter的才是真正的區(qū)別。 默認情況下,POGO中的每個屬性都會獲得一個匹配集。
再回想一下您的上一個Java項目。你是精心手工制作了每個getter和setter,還是讓IDE生成了代碼?
如果這段代碼是死記硬背的,并且沒有什么意思,那么就讓Groovy編譯器代替您的IDE來為您生成它,可以極大地減少項目中的視覺混亂。而且,如果您碰巧覆蓋了默認值
getter或setter的行為,看看你的眼睛是如何被規(guī)則的例外吸引的:
class Book{
String title
String author
Integer pages
String getTitle(){
return title.toUpperCase()
}
}
Getter and Setter Shortcut Syntax(Getter和Setter快捷語法)
class Book{
String title
}
Book book = new Book()
book.title = "Groovy Recipes"
//book.setTitle("Groovy Recipes")
println book.title
//println book.getTitle()
===> Groovy Recipes
Groovy減少視覺混亂的另一個方法是在處理類屬性時允許的語法捷徑。book.title
在幕后調(diào)用book.getTitle()
。這是一種使它感覺更自然的嘗試——似乎是直接處理圖書的標題,而不是調(diào)用返回字符串值的Book類的getTitle()
方法。(有關(guān)更多信息,請參見下一頁的側(cè)欄。)
遺留的Java的getter
和setter
語法在Groovy中仍然是完全有效的。
Suppressing Getter/Setter Generation(抑制生成Getter/Setter)
class Book2{
private String title
}
println Book2.getDeclaredField("title")
===> private java.lang.String Book2.title
println Book2.methods.each{println it}; "DONE"
// neither getTitle() nor setTitle() should appear in the list
在Groovy中顯式地將字段標記為private會抑制相應(yīng)的getter和setter方法的創(chuàng)建。如果您希望字段對Java類真正隱藏起來,那么這個小工具非常有用。
::: alert-info
Groovy語法快捷鍵
如第4.2節(jié)“Getter和Setter快捷語法”所示,在前一頁,book.getTitle()
可以縮寫為book.title
。雖然這個getter/setter
快捷方式是Groovy中的默認行為,但是在語言中有很多地方它被選擇性地覆蓋,以表示完全不同的意思。
在第3.15節(jié),Map快捷方式,在62頁,一個像書一樣的調(diào)用。hashmap上的book.title
是book.get("title")
的快捷方式。在第7章解析XML中,在第116頁,同樣的調(diào)用是解析XML片段的一種快速方法,如<book><title>Groovy Recipes</title></book>
。在第10.8節(jié)中,調(diào)用不存在的方法(invokeMethod),在第193頁,您將學習如何接受該調(diào)用并使用它做幾乎任何您想做的事情。
我不認為這是一個陷阱;事實上,我認為它是一個強大的語言特性。但如果你沒有預料到,它會讓你猝不及防。
:::
但是其他Groovy類的可見性又如何呢?好吧,這段代碼應(yīng)該非常清楚,字段仍然是可訪問的,盡管缺乏getter和setter方法:
def b2 = new Book2()
b2.title = "Groovy Recipes"
println b2.title
===> Groovy Recipes
Groovy在隱私方面存在一些問題——簡而言之,它忽略了私有修飾符。(是的,這是一個相當大的問題。有關(guān)更多信息,請參閱第80頁的側(cè)欄。)
如果希望保護私有字段不受Groovy中意外修改的影響,可以添加一對不做任何事的getter
和setter
。將這些方法標記為私有將防止它們擾亂公共API。
class Book3{
private String title
private String getTitle(){}
private void setTitle(title){}
}
def b3 = new Book3()
b3.title = "Groovy Recipes"
println b3.title
===> null
4.3 getProperty和setProperty
class Book{
String title
}
Book book = new Book()
book.setProperty("title", "Groovy Recipes")
//book.title = "Groovy Recipes"
//book.setTitle("Groovy Recipes")
println book.getProperty("title")
//println book.title
//println book.getTitle()
===> Groovy Recipes
這個例子展示了在POGO上設(shè)置和獲取屬性的第三種方法–book.getProperty()
和book.setProperty()
。在傳統(tǒng)Java中,調(diào)用book.getTitle()
是第二天性。正如我們在4.2節(jié)中討論的,Getter和Setter快捷語法,在第72頁,Groovy允許您將book.getTitle()
縮短為book.title
。但是,如果希望使用更通用的方法來處理類的字段,該怎么辦呢?
Groovy借鑒了 java.lang.System
的技巧,它提供了一種訪問類屬性的通用方法。 如第5.8節(jié)“獲取系統(tǒng)屬性”(第92頁)中所述,您無法進行諸如 System.getJavaVersion()
之類的方法調(diào)用。 您必須以更通用的方式要求系統(tǒng)屬性- System.getPropery(" java.version")
。 要獲取所有適當關(guān)系的列表,請輸入 System.getProperties()
。 現(xiàn)在,通過 groovy.lang.GroovyObject
接口可以在每個類上使用這些通用方法。
是的,您總是可以使用java.lang.reflect
包來完成這種事情,但是Groovy使該語法易于使用。 一旦您開始更常規(guī)地處理元編程,與類進行交互的這種方式將與 book.getTitle()
或book.title
一樣自然。 有關(guān)此內(nèi)容的更多信息,請參見第10.2節(jié),發(fā)現(xiàn)類的字段,第183頁。
Property Access with GStrings(使用GStrings進行屬性訪問)
class Book{
String title
}
def b = new Book()
def prop = "title"
def value = "Groovy Recipes"
b."${prop}" = value
println b."${prop}"
===> Groovy Recipes
與getProperty
和setProperty
方法一樣,還有一種更“出色”的方法來處理字段。您可以將字段的名稱傳遞給GString以獲得最大的靈活性。(有關(guān)GStrings的更多信息,請參見第3.13節(jié),GStrings,第57頁。)
4.4 使屬性只讀
class Book{
final String title
Book(title){
this.title = title
}
}
Book book = new Book()
book.title = "Groovy Recipes"
//===>
//ERROR groovy.lang.ReadOnlyPropertyException:
//Cannot set readonly property: title for class: Book
Book book2 = new Book("GIS for Web Developers")
println book2.title
//===>
//GIS for Web Developers
最終修飾符在Groovy和Java中的工作方式相同。 具體來說,這意味著只能在實例化類時才能設(shè)置屬性。 如果您嘗試在事實之后修改屬性,則會引發(fā) groovy.lang.ReadOnlyPropertyException
。
4.5 構(gòu)造函數(shù)快捷語法
class Book{
String title
String author
Integer pages
}
Book book1 = new Book(title:"Groovy Recipes", author:"Scott Davis", pages:250)
Book book2 = new Book(pages:230, author:"Scott Davis",
title:"GIS for Web Developers")
Book book3 = new Book(title:"Google Maps API")
Book book4 = new Book()
Groovy為構(gòu)造函數(shù)提供了便利,這是您在Java中從未見過的。 通過支持命名參數(shù)和變長參數(shù)列表,您可以按照自己認為合適的任何方式實例化類。 book1和book2演示了由于已命名變量,因此您可以按任何順序提供它們。 book3演示了等式的vararg部分:在這種情況下,您只需輸入標題即可。 book4演示了Groovy便捷方法中的任何一個都不會干擾默認的Java構(gòu)造函數(shù)。
這個構(gòu)造函數(shù)快捷方式的特別之處在于,它也可以在純Java類中使用。構(gòu)造函數(shù)行為是在運行時添加的,因此它既適用于Groovy也適用于Java類。有關(guān)這方面的實際演示,請參見第4.9節(jié),從Groovy調(diào)用Java,見第81頁。
4.6 可選參數(shù)/默認值
class Payment{
BigDecimal amount
String type
public Payment(BigDecimal amount, String type="cash"){
this.amount = amount
this.type = type
}
String toString(){
return "${amount} ${type}"
}
}
def pmt1 = new Payment(10.50, "cash")
println pmt1
//===> 10.50 cash
def pmt2 = new Payment(12.75)
println pmt2
//===> 12.75 cash
def pmt3 = new Payment(15.99, "credit")
println pmt3
//===> 15.99 credit
在本例中,除非顯式提供另一個值,否則輸入默認值“cash”。這簡化了開發(fā)過程,不需要您維護兩個單獨的重載構(gòu)造函數(shù)—一個只接受數(shù)量,另一個接受數(shù)量和類型??蛇x參數(shù)的真正好處在于,它們可以用于任何類型的方法。請考慮以下簡化電影票購買的方法:
class Ticket{
static String buy(Integer quantity=1, String ticketType="adult"){
return "${quantity} x ${ticketType}"
}
}
println Ticket.buy()
println Ticket.buy()
println Ticket.buy(2)
println Ticket.buy(4, "child")
===>
1 x adult
1 x adult
2 x adult
4 x child
在本例中,單一方法提供了極大的靈活性。如果您在沒有參數(shù)的情況下調(diào)用它,它將對所有內(nèi)容使用智能默認值。下一個最有可能的場景(理論上)是兩個人約會——代碼允許您覆蓋數(shù)量,同時仍然默認票證類型為“adult”。
在支付示例中,金額沒有默認值。您需要提供它每次您創(chuàng)建一個新的付款。另一方面,如果沒有提供,則默認為“cash”??蛇x參數(shù)必須總是在所有必需參數(shù)之后??蛇x參數(shù)也應(yīng)該按重要程度排序——最可能更改的參數(shù)應(yīng)該在列表的最前面,其次是最可能更改的參數(shù),以此類推,最后是最不可能被覆蓋的參數(shù)。
static String buy(Integer quantity=1, String ticketType="adult",BigDecimal discount=0.0)
//won't compile
Ticket.buy(0.15)
//will compile
Ticket.buy(1, "adult", 0.15)
考慮到新buy()方法中參數(shù)的順序,您不可能在不指定所有三個值的情況下請求一張成人票的15%折扣。optionals列表中的級聯(lián)重要性順序表明,可以安全地忽略右邊的參數(shù),但是必須指定左邊的參數(shù)。
4.7 私有方法
class Book{
String title
private String getTitle(){
return title
}
private void setTitle(String title){
this.title = title
}
private void poke(){
println "Ouch!"
}
}
Book book = new Book()
// 注意,Groovy完全忽略了私有訪問修飾符
book.title = "Groovy Recipes"
println book.title
===> Groovy Recipes
book.poke()
===> Ouch!
簡單地說,Groovy不關(guān)心方法的私有訪問修飾符。您可以像調(diào)用公共方法一樣輕松地調(diào)用私有方法。(有關(guān)更多信息,請參見下一頁的側(cè)欄。)
私有方法不會顯示在公共界面中。 也就是說,當您調(diào)用Book.methods.each {println it}
時, poke()
不會出現(xiàn)。 您知道 poke()
可用的唯一方法是,如果您前面有源代碼。
Java尊重private修飾符。 在Java中實例化時,不能通過常規(guī)方式調(diào)用poke()。
4.8 從Java調(diào)用Groovy
public class BookstoreJava implements Bookstore {
private Book b; // written in Groovy
private Publisher p; // written in Java
public Book makeBook() {
b = new Book();
b.setAuthor("Scott Davis");
b.setTitle("Groovy Recipes");
b.setPages(250);
return b;
}
public Publisher makePublisher() {
p = new Publisher();
p.setName("Pragmatic Bookshelf");
return p;
}
}
此時,您可能正在尋找Book是用Groovy實現(xiàn)的,而Publisher是用Java實現(xiàn)的證據(jù)。這就是重點!一旦用Groovy編寫的類被編譯,它看起來與用Java編寫的類沒有什么不同。自動生成的getter和setter(第4.2節(jié),自動生成的getter和setter,在第71頁)與Java實現(xiàn)的getter和setter沒有什么區(qū)別。這使得Groovy成為JavaBeans的完美替代品。
::: alert-info
陷阱:Groovy忽略私有修飾符
如第78頁的第4.7節(jié)私有方法所示,Groovy允許您像調(diào)用公共方法一樣輕松地調(diào)用類的私有方法。正如第4.2節(jié)(抑制Getter/Setter生成)中所演示的,在第72頁,Groovy允許您像訪問公共字段一樣訪問私有字段。
底線是Java尊重私有訪問修飾符;Groovy不。Java是敲你前門的鄰居,即使它知道你把鑰匙藏在哪里。Groovy是一個讓自己進來借一杯糖,然后在廚房桌子上給你留一張紙條的鄰居。當我第一次使用Groovy時,這是我發(fā)現(xiàn)的最令人不安的(咳咳)特性。在最好的情況下,忽略私人修飾語似乎是不禮貌的。在最壞的情況下,這可能是完全危險的。
也許是Groovy對隱私的漫不經(jīng)心的態(tài)度讓我最初感到不舒服。很容易調(diào)用一個私有方法,你會想,“這一定是個bug。”當然,您也可以通過使用java.lang.reflect
繞過Java中的私有修飾符。但是由于某些原因,在Java中調(diào)用私有方法似乎更加謹慎。在Java中,您必須有意識地去調(diào)用私有方法。你必須知道你在做什么。我們遠離了Java的老路——毫無疑問,我們正在做一些不同尋常的事情。
雖然Groovy中缺乏隱私的問題仍然偶爾困擾著我,但在實踐中這并不是什么大問題。私有方法不會出現(xiàn)在公共接口中,所以通常我知道私有方法存在的唯一方法是打開源代碼。如果我有那么多機會去上課,我就有責任不把事情搞砸。按照同樣的思路,在為單元測試準備類時,訪問私有方法和字段實際上非常有用,特別是如果編寫的類不是很容易測試的話。
Bjarne Stroustrup曾有句著名的話:“ C可以很容易地將自己拍到腳上; C ++使它變得更難,但是當您這樣做時,它會使您全力以赴。”有些人可能會說,在private methods
的案例中,Groovy讓炸掉整條腿變得更容易了。我個人對這個問題的看法更務(wù)實一些:我寧愿要一把更鋒利的手術(shù)刀和一個訓練有素的外科醫(yī)生,也不愿要一把更鈍的刀片。開發(fā)人員有責任明智地使用這個特性。
:::
使用純Java實現(xiàn)中必須使用的一小部分代碼就可以獲得相同的行為。這段代碼唯一需要做的事情就是編譯Groovy類(我們將在下一頁的Groovy聯(lián)合編譯器4.11節(jié)中討論),并且在$GROOVY_HOME/embeddable
中找到的單個Groovy JAR位于類路徑的某個地方。
4.9 從Groovy調(diào)用Java
class BookstoreGroovy implements Bookstore{
Book b // written in Groovy
Publisher p // written in Java
Book makeBook(){
b = new Book(author:"Scott Davis", pages:250, title:"Groovy Recipes")
}
Publisher makePublisher(){
p = new Publisher(name:"Pragmatic Bookshelf")
}
}
在第79頁的第4.8節(jié)“從Java調(diào)用Groovy”中,我們看到Groovy類在從Java運行時看起來就像Java類。在這個例子中,您可以看到Java類在從Groovy運行時看起來就像Groovy類。即使Publisher是用Java編寫的,您仍然可以使用Groovy中提供的很酷的構(gòu)造函數(shù)快捷方式(第4.5節(jié),構(gòu)造函數(shù)快捷語法,見第76頁)。
4.10 Groovy和Java中的接口
// Bookstore.java
public interface Bookstore {
public Book makeBook();
public Publisher makePublisher();
}
// BookstoreGroovy.groovy
class BookstoreGroovy implements Bookstore{...}
// BookstoreJava.java
public class BookstoreJava implements Bookstore {...}
您在這里看到的是Groovy與Java無縫集成的另一個例子。Bookstore接口是用Java編寫的。如前所述,Book是用Groovy編寫的,Publisher是用Java編寫的。這個接口可以很好地處理這兩個類。
現(xiàn)在看看BookstoreGroovy。它是用Groovy編寫的,但是它能夠像BookstoreJava一樣輕松地實現(xiàn)Bookstore(用Java編寫)。
這段代碼唯一需要做的事情就是編譯您的Groovy類(我們將在第4.11節(jié),Groovy聯(lián)合編譯器中對此進行討論),并且在$GROOVY_HOME/embeddable
中找到的單個Groovy JAR位于類路徑的某個地方。
4.11 Groovy聯(lián)合編譯器
// compile Groovy code
$ groovyc *.groovy
// compile Java code
$ javac *.java
// compile both Groovy and Java code
// using groovyc for the Groovy code and javac for the Java code
$ groovyc * -j -Jclasspath=$GROOVY_HOME/embeddable/groovy-all-1.5.0.jar:.
毫不奇怪,groovyc將Groovy源代碼編譯成字節(jié)碼,就像javac編譯Java源代碼一樣。然而,Groovy編譯器增加了一個更微妙但非常有用的特性:使用單個命令聯(lián)合編譯Java和Groovy代碼的能力。
滿足依賴關(guān)系
為了理解groovyc的功能,讓我們更深入地研究一下javac的生命周期。在javac編譯您的代碼之前,它必須滿足所有的依賴項。例如,讓我們嘗試編譯Bookstore接口:
$ javac Bookstore.java
// Bookstore.java
public interface Bookstore {
public Book makeBook();
public Publisher makePublisher();
}
javac要做的第一件事就是查找Book 和Publisher。沒有它們,Bookstore就不可能被編輯。因此,javac在類路徑中搜索"Book.class"和"Publisher.class"。它們可能存儲在JAR中,也可能只是隨意放置,但是如果javac能夠在已經(jīng)編譯的狀態(tài)中找到它們,那么它就可以繼續(xù)編譯Bookstore。
如果javac找不到"Book.class"或"Publisher.class",然后查找"Book.java"和"Publisher.java"。如果能夠找到源代碼,它將代表您編譯它們,然后繼續(xù)編譯Bookstore。明白了嗎?
好的,那么Groovy代碼是如何在這個過程中產(chǎn)生干擾的呢?不幸的是,javac只知道如何編譯Java代碼。有幾種可插入的編譯器可用來管理許多不同類型的源代碼——GNU GCC編譯器[^411]就是一個很好的例子。遺憾的是,javac不是其中之一。如果它找不到Book.class or Book.java,它放棄了。在我們的例子中,如果Book是用Groovy編寫的,javac會這樣說:
$ javac Bookstore.java
Bookstore.java:2: cannot find symbol
symbol : class Book
location: interface Bookstore
public Book makeBook();
^
1 error
在這個簡單的示例中,變通辦法是“嘿,醫(yī)生,這樣做時會很痛”。 由于javac不會為您編譯Groovy代碼,因此請嘗試先編譯"Book.groovy",然后再編譯"Bookstore.java":
$ groovyc Book.groovy
$ javac Bookstore.java
$ ls -al
-rw-r--r-- 1 sdavis sdavis 5052 Dec 10 17:03 Book.class
-rw-r--r--@ 1 sdavis sdavis 60 Dec 10 16:57 Book.groovy
-rw-r--r-- 1 sdavis sdavis 169 Dec 10 17:03 Bookstore.class
-rw-r--r--@ 1 sdavis sdavis 93 Dec 10 16:56 Bookstore.java
-rw-r--r-- 1 sdavis sdavis 228 Dec 10 17:03 Publisher.class
-rw-r--r--@ 1 sdavis sdavis 48 Dec 10 16:58 Publisher.java
世界一切都很好,對吧? 您將"Book.groovy"編譯為字節(jié)碼,這使javac可以在沒有抱怨的情況下編譯"Bookstore.java"。 (請注意,Publisher.java與Bookstore.java是免費編譯的。)
盡管對于簡單的項目,手動管理Groovy/Java依賴關(guān)系鏈是可行的,但是如果您擁有依賴于"依賴Groovy類的Java類的"Groovy類,它很快就會成為噩夢。
一個命令,兩個編譯器
$ groovyc * -j -Jclasspath=$GROOVY_HOME/embeddable/groovy-all-1.5.0.jar:.
由于無法幫助javac編譯Groovy,因此您可以使用groovyc來實現(xiàn)此功能。 但是請不要誤解,groovyc不會編譯Java代碼。 通過將-j
標志傳遞給編譯器,它向編譯器發(fā)出信號,使其將Javac用于Java代碼,并將groovyc用于Groovy代碼。 使用每種語言的本機編譯器,您將獲得兩種語言之間的依賴關(guān)系解析的所有好處。
小寫的-j標志打開聯(lián)合編譯。 您可以包括多個大寫的-J標志,以將標準標志傳遞給javac編譯器。 此示例確保javac可以通過傳入classpath參數(shù)來找到Groovy JAR。 如果未設(shè)置CLASSPATH環(huán)境變量,則必須使用classpath標志。 如果您在類路徑中沒有Groovy JAR,則Java代碼將無法針對Groovy類進行編譯。
在此示例中,您告訴javac生成與Java 1.4兼容的類:
$ groovyc * -j -Jclasspath=$GROOVY_HOME/embeddable/groovy-all-1.5.0.jar:. -Jsource=1.4 -Jtarget=1.4
4.12 用Ant編譯項目
<taskdef name="groovyc"
classname="org.codehaus.groovy.ant.Groovyc"
classpathref="my.classpath"/>
<groovyc
srcdir="${src}"
destdir="${dest}"
classpathref="my.classpath"
jointCompilationOptions="-j -Jsource=1.4 -Jtarget=1.4" />
很高興知道您可以從命令行編譯Groovy代碼(Groovy Joint Compiler,第4.11節(jié),第82頁),但是大多數(shù)項目都使用Ant。 幸運的是,Groovy在這種情況下提供了Ant任務(wù)。
為了避免taskdef步驟,將Groovy JAR從 $GROOVY_HOME/embeddable
放到 $ANT_HOME/lib
目錄中。文章來源:http://www.zghlxwxcb.cn/news/detail-472071.html
4.13 使用Maven編譯項目
http://mojo.codehaus.org/groovy
雖然Groovy不提供Maven 2.0開箱即用的支持,但是Mojo項目提供了這種支持。有一個Maven插件允許您聯(lián)合編譯Groovy代碼(詳細信息請參閱第82頁的第4.11節(jié),Groovy聯(lián)合編譯器)。還有一個Maven原型插件,它為您的Groovy項目生成一個框架。文章來源地址http://www.zghlxwxcb.cn/news/detail-472071.html
到了這里,關(guān)于Groovy食譜: 第4章 Java和Groovy集成的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!