javagroovy
A. 在java中使用groovy怎麼搞
一種基於Java虛擬機的動態語言,可以和java無縫集成,正是這個特性,很多時候把二者同時使用,把groovy作為java的有效補充。對於Java程序員來說,學習成本幾乎為零。同時支持DSL和其他簡介的語法(例如閉包),使代碼便於閱讀。可以用groovy的動態特性來做規則引擎,在DB中維護腳本,業務變化的時候讓應用系統動態載入。
如果引入groovy在java工程中?
這個很簡單,不需要做別的事情,僅僅把groovy的二方包加入到pom文件中即可。例如:
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version> 1.8 . 3 </version>
</dependency>
java和groovy混合使用的方法有幾種?
1、 靜態編譯 ,在java工程中直接寫groovy的文件,然後可以在groovy的文件中引用java工程的類,這種方式能夠有效的利用groovy自身的語言特性,例如閉包;
2、通過 groovyShell 類直接執行腳本,例如:
package groovy_dsl.shell;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
public class GroovyShellEx {
public static void main(String[] args) {
Binding bind = new Binding();
bind.setVariable( "name" , "iamzhongyong" );
bind.setVariable( "age" , "25" );
GroovyShell shell = new GroovyShell(bind);
Object obj = shell.evaluate( "str = name+age;return str" );
System.out.println(obj);
}
}
3、通過 groovyScriptEngine 執行文件或者腳本,例如:
package groovy_dsl.script;
import groovy.util.GroovyScriptEngine;
public class ScriptEngine {
public static void main(String[] args) throws Exception {
GroovyScriptEngine engine = new GroovyScriptEngine( "" );
Object obj = engine.run( "src/main/java/groovy_dsl/script/script_test.groovy" , "iamzhongyong" );
System.out.println(obj);
}
}
4、通過 GroovyClassLoader 來執行,例如:
package groovy_dsl.classloader;
import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import java.io.File;
import java.io.IOException;
public class GroovyClassLoaderEx {
public static void main(String[] args) throws Exception, IOException {
GroovyClassLoader loader = new GroovyClassLoader();
for ( int i= 0 ;i< 100 ;i++){
Class<?> clazz = loader.parseClass( new File( "src/main/java/groovy_dsl/classloader/UserDO.groovy" ));
GroovyObject clazzObj = (GroovyObject)clazz.newInstance();
clazzObj.invokeMethod( "setName" , "iamzhongyong" );
clazzObj.invokeMethod( "setSex" , "Boy" );
clazzObj.invokeMethod( "setAge" , "26" );
System.out.println(clazzObj.invokeMethod( "getAllInfo" , null ));
}
}
}
使用groovy尤其需要主要的問題?
通過看groovy的創建類的地方,就能發現,每次執行的時候,都會新生成一個class文件,這樣就會導致JVM的perm區持續增長,進而導致FullGCc問題,解決辦法很簡單,就是腳本文件變化了之後才去創建文件,之前從緩存中獲取即可。
groovy中的源碼如下:
return parseClass(text, "script" + System.currentTimeMillis() + Math.abs(text.hashCode()) + ".groovy" );
這個是增加緩存的代碼:
GroovyClassLoader groovyClassLoader = new GroovyClassLoader(GroovyScriptExecute. class .getClassLoader());
Class<?> groovyClass = null ;
String classKey = String.valueOf(scriptClass.hashCode());
//先從緩存裡面去Class文件
if (GroovyScriptClassCache.newInstance().containsKey(classKey)){
groovyClass = GroovyScriptClassCache.newInstance().getClassByKey(classKey);
} else {
groovyClass = groovyClassLoader.parseClass(scriptClass);
GroovyScriptClassCache.newInstance().putClass(classKey, groovyClass);
}
GroovyObject go = (GroovyObject)groovyClass.newInstance();
下面這個是緩存的單例類,貼一下:
public class GroovyScriptClassCache {
private static final Map<String /*class文件的描述*/ ,Class<?>> GROOVY_SCRIPT_CLASS_CACHE = new HashMap<String,Class<?>>();
private GroovyScriptClassCache(){}
private static GroovyScriptClassCache instance = new GroovyScriptClassCache();
public static GroovyScriptClassCache newInstance(){
return instance;
}
public Class<?> getClassByKey(String key){
return GROOVY_SCRIPT_CLASS_CACHE.get(key);
}
public void putClass(String key,Class<?> clazz){
GROOVY_SCRIPT_CLASS_CACHE.put(key, clazz);
}
public boolean containsKey(String key){
return GROOVY_SCRIPT_CLASS_CACHE.containsKey(key);
}
}
為啥要每次new一個GroovyClassLoader,而不是所有的腳本持有一個?
因為如果腳本重新載入了,這時候就會有新老兩個class文件,如果通過一個classloader持有的話,這樣在GC掃描的時候,會認為老的類還在存活,導致回收不掉,所以每次new一個就能解決這個問題了。
注意CodeCache的設置大小
對於大量使用Groovy的應用,尤其是Groovy腳本還會經常更新的應用,由於這些Groovy腳本在執行了很多次後都會被JVM編譯為native進行優化,會占據一些CodeCache空間,而如果這樣的腳本很多的話,可能會導致CodeCache被用滿,而CodeCache一旦被用滿,JVM的Compiler就會被禁用,那性能下降的就不是一點點了。
Code Cache用滿一方面是因為空間可能不夠用,另一方面是Code Cache是不會回收的,所以會累積的越來越多(其實在不採用groovy這種動態更新/裝載class的情況下的話,是不會太多的),所以解法一可以是增大code cache的size,可通過在啟動參數上增加-XX:ReservedCodeCacheSize=256m(Oracle JVM Team那邊也是推薦把code cache調大的),二是啟用code cache的回收機制(關於Code Cache flushing的具體策略請參見此文),可通過在啟動參數上增加:-XX:+UseCodeCacheFlushing來啟用。
B. Java程序員為什麼學習Groovy
正如Groovy對Java很多特性進行的包裝優化一樣,基於Groovy的HttpBuilder也包裹了HttpClient,使網路編程變得更加的方便易用,下面稍微來用一個例子看一下。
尋找各種依賴的jar包有時候會讓我們失去耐心,不過值得慶幸的是我們有Maven和Gradle這樣的工具,可以根據配置輕松的幫我們配置好我們需要的數據。下面我們來敘述一下整個過程。
1. 創建文件夾httpbuildertest
2. 創建gradle配置文件,build.gradle,內容如下:
apply plugin: "groovy"apply plugin: "eclipse"repositories { mavenCentral()}dependencies { compile "org.codehaus.groovy:http-builder:0.4.0" compile "org.codehaus.groovy:groovy-all:2.3.3" testCompile "org.spockframework:spock-core:0.7-groovy-2.0"}
gradle我們將做另文介紹
3. 執行gralde eclipse(當然必須先安裝gradle),就可以生成eclipse所需要的.classpath和.project文件,這時候就可以使用eclipse導入功能來import->Existing Projects Into WorkSpace。
4. 創建我們的一個測試,試試看是不是可以使用httpbuilder了
import groovyx.net.http.HTTPBuilderimport spock.lang.Specification;import static groovyx.net.http.Method.*import static groovyx.net.http.ContentType.*class HttpbuildLabSpec extends Specification{HTTPBuilder http = new HTTPBuilder( 'http://m.weather.com.cn' )public void testRequestWeather(){ when: def info ="" http.request( GET, JSON ) { url.path = '/data/101290401.html' headers.'User-Agent' = 'Mozilla/5.0 Ubuntu/8.10 Firefox/3.0.4' response.success = { resp, json -> info = json.weatherinfo.city } response.failure = { resp -> println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}" } } then:"曲靖"==info}}
打完收工,通過這個小例子我們可以了解到這么一些內容:
(1)HTTPBuilder 是這個框架的核心類(要不然怎麼和框架一個名字),構建這個類的對象的時候,指定要請求的baseUrl。
(2)request方法可以指定請求的method和返回的數據格式,method對應的是GET/PUT/POST/DELETE/HEAD幾個常量,而數據格式目前有JSON/XML/HTML/BINARY/URLENC/ANY幾種。
(3)一個比較有意思的地方是,在http的request方法裡面,彷彿是無根之水一樣突然冒出來了幾個沒有聲明過的變數,看起來連編譯也不會通過的方法,那麼是如何能正常運作的呢?這個我們就要研究到Groovy的Closure(閉包)。Groovy的閉包里包含有一個delegate屬性,一般來說,這個delegate里保存的是閉包使用上下文的對象引用,比如a調用了一個閉包b,則b的delegate就是a的this對象。而在HTTPBuilder對象調用request方法的時候,它把傳入閉包的delegate改成了一個叫做SendDelegate的類對象(這是HTTPBuilder的內部類,他們都是用Java寫的,在新版的HttpBuilder里,已經改名為RequestConfigDelegate),這個類裡面,分別包含了一個叫做getHeaders()的方法,一個叫做getUrL()的方法,一個叫做getResponse()的方法。稍微思索一下我們就可以想到,Groovy里有這樣的特性,如果直接使用一個識別不出來的變數,Groovy會假設它是getter的一種簡寫形式,自動進行補全(當然這也是DSL的常用伎倆,把方法偽裝成短語),而getter並沒有參數,所以其括弧是可以簡寫的,實際上上面的代碼可以寫作getUrl().path = '/data/101290401.html',這樣就非常符合程序員的視覺體驗了。
(4)第四點羅嗦了不少,主要是為了喜歡追根問題的同學釋疑,實際上整個調用還是非常的簡單明快的,在request閉包里,我們通過response(記得嗎,實際上就是GetResponse()),獲得了一個Map結構,這個Map的內部結構實際上是Map<String,Closure>,對「success」和「failure」這兩個key我們分別設置了對應的閉包,這樣就完成了回調的設置,一旦方法成功或者失敗,就可以調用到對應的閉包。
(5)使用了JSON作為返回格式,閉包的第二個參數就是解析好的返回body,就是一個Json對象,是可以直接用點號來訪問的。當然最好不要在失敗的閉包里放這個參數,一般失敗的情況比較多,也許就是一個html返回,格式錯誤那麼測試也就無法按照預期進行了。
C. java程序員為什麼使用Groovy
Groovy是一門基於JVM的腳本語言。它在兼容Java語法的同時,借鑒了Ruby、Python等語言的特性,有自己一套簡潔而靈活的語法。同時,運行在JVM上也意味著它也可以使用Java語言編寫的庫。這兩點結合,讓Groovy極其適合編寫Java代碼的測試腳本。
選擇Groovy作為測試腳本的語言的原因:
Groovy基於JVM,這使我能夠調用產品的Java代碼,也能夠調用Java標准庫里的代碼。除些之外,還可以通過Maven或Gradle使用大量的第三方Java庫。
Groovy是動態語言,擴展了Java的容器類,提供了完善的函數式編程和元編程支持。這讓我們可以寫出簡潔而富有表現力的代碼。
Groovy提供了大量的語法糖。與Java自身繁冗的代碼相比,這些語法糖大大節約了我們編寫腳本的時間,減少了我的腳本的代碼量。
然而,Groovy在帶來上述三個優點的同時,也會帶來有相應的缺點:
效率問題。Groovy作為運行在JVM上的動態語言,運行效率是低於Java的。雖然可以用@CompileStatic註解來靜態編譯一些類以提高效率,但這樣又會失去Groovy的一些動態語言的特性。
語法過於靈活,運用不當會降低可讀性與可維護性。Groovy支持元編程特性,可以在運行時動態添加方法。這一點自然可以簡化代碼,但也有很大的可能會降低可維護性。函數式編程與大量的語法糖會讓不熟悉Groovy的人讀起來一頭霧水,反而降低了可讀性。
D. Java和Groovy的區別
Groovy 是 JVM 的一個替代語言 — 替代 是指可以用 Groovy 在 Java 平台上進行 Java 編程,使用方式基本與使用 Java 代碼的方式相同。
Groovy 的一個好處是,它的語法與 Java 語言的語法很相似。雖然 Groovy 的語法源於 Smalltalk 和 Ruby 這類語言的理念,但是可以將它想像成 Java 語言的一種更加簡單、表達能力更強的變體。(在這點上,Ruby 與 Groovy 不同,因為它的語法與 Java 語法差異很大。)
E. Java程序員為什麼學習Groovy
要成為好的JAVA程序員,不但需要會JAVA一種語言,還應該要會以JVM作為運行平台的其他語言,因為JVM支持下的語言在現在已經發展出很多種了,而且每種語言都有自己的優勢,有些可以很簡便地實現多線程編程,有些則對函數式編程有非常好的支持,而你在做項目的時候,針對不同的模塊,可以使用不同的語言去實現,從而加快項目進度,因為JVM支持下的不同語言之間是很容易就能實現交互的。 望採納!
F. Java程序員為什麼學習Groovy
groovy、kotlin、scala等都是基於jvm平台的語言(都會編譯成位元組碼),並且可以和java混合使用。
他們對java進行了不同程度的改良,語法結構、集合操作方式、更多的語法糖、泛型的支持(java是偽泛型),更好的lambda表達式語法等等。一般來講這些語言可以大幅度提高生產效率,比如kotlin可以節省1/3的代碼量。
從日常使用的角度,建議學習kotlin,當前kotlin已經被google確定為新任官方語言。如果做android開發,不至於再多學習一門語言。
G. java和groovy能混編嗎
java和groovy肯定能混編,
java & groovy混編:一種最「勢利」的折衷而groovy,說它是java++也不為過,因為java代碼直接就可以被groovy編譯, groovy完全兼容java語法。
H. groovy語言主要是用來干什麼,和JAVA的區別是什麼
Groovy是Java平台上設計的面向對象編程語言。這門動態語言擁有類似Python、Ruby和Smalltalk中的一些特性,可以作為Java平台的腳本語言使用。 groovy的語法跟java完全按類似。
它和java的區別是:
一:java為強類型的語言;Groovy為弱類型,可以自動推斷類型;
創建數組的時候Groovy的語法為:def intArray=[2,3,4]
創建MAP的時候Groovy的語法為:def m={}
二:Groovy默認訪問修飾符為Public,可以不寫訪問修飾符
可以直接用def關鍵字定義,如:
def sayHello(){}
限定訪問范圍
@PackageScope修飾方法
I. Java程序員為什麼學習Groovy
首先Groovy也是運行在java虛擬機上的,二者有語法上的區別但是和java並沒有本質上的不同。
Groovy和java是相結合的關系而並不是將java取而代之。
1、Java開發者學習Groovy的成本很低
2、是一種成熟的面向對象編程語言,既可以用於面向對象編程,又可以用作純粹的腳本語言
3、完成同樣的事情Groovy可能比Java需要寫的代碼要少
4、支持單元測試和模擬(對象),可以 簡化測試
5、groovy中基本類型也是對象,可以直接調用對象的方法
......
1
2
3
4
5
6
7
8
9
def var="hello "+
"world"+
",groovy!"
def repeat(val){
for(i = 0; i < 5; i++){
println val
}
}
repeat(var)
輸出:
hello world,groovy!
hello world,groovy!
hello world,groovy!
hello world,groovy!
hello world,groovy!
最後,為什麼要學,這是給那些比較「懶」的java程序員准備的,代碼量小啊,而且一些新特性用起來也很方便省心。
J. java和groovy能混編嗎
答案是肯定的,java & groovy混編:一種最「勢利」的折衷
而groovy,說它是java++也不為過,因為java代碼直接就可以被groovy編譯, groovy完全兼容java語法, 對一般java開發人員來說,這真是太親切了