Groovyの入門
GroovyはJVM上で動的言語で、Javaは最終的にはJVM上で実行するコンパイルされた.classすることが、彼に似た構文。
Groovyのは、Javaとし、これに基づいて完全な互換性があり、動的タイプと、そのような閉鎖のためのサポートなど柔軟な機能の多くを追加DSLをサポートし、非常に柔軟で動的なスクリプト言語です。
この記事では、私が書く方法を知っている、のGradleスクリプトのコードを読むことができるようにすることです。だから私は、Groovyのにはなりません。
各ビルドスクリプトの設定ファイルは、Groovyのスクリプトファイルです。これでは、Groovyの構文に合わせて任意のコードを書くことができます。
例えば、クラス定義、メソッド、およびその他の変数の場合。Groovyのは、Javaと完全に互換性があるため、それは任意のJavaコードを記述することも可能であり、完全な互換性があります。
DSL
DSL(ドメイン固有言語)中国の意味は、ドメイン固有言語、特定の領域に特別な注意、その場所ではなく、全体です。だから、ドメイン固有です。
GradleのGroovyのスクリプトを具体的に構築された自動化に取り組むDSL、DSLに基づいています。
私たちは、DSLの心であるビルオートメーションの目的を達成することができますGradleのスクリプトを設定し、適切な構文に従う必要があります。
注記
単一行コメント
//这里是注释
def name = "佛系编码"
複数行コメント
/* 这里是多行注释
啦啦啦啦 */
docコメント
/**
* 这里是 doc 注释
* 啦啦啦啦
*/
データの種類
Javaの、それがサポートしているオブジェクト内の基本的なデータ型、に加えて、
閉鎖
一覧を強化し、コレクションの地図
強化ファイル、ストリームおよびIOの他のタイプ
タイプは、明示的にデフ宣言することができるにも宣言された型のDEFをGroovyのでしょう型推論のために、宣言するために使用することができます。
Javaの基本データ型が同じで、彼らが出てくることはありません。それ以下では、オブジェクト、文字列、閉鎖等。
さらに:グルービーセミコロンを省略してもよいです。
弦
単一引用符と二重引用符を使用すると、文字列定数を定義することができます。
違いは、単に単一引用符の文字列である、あなたは表現、計算、評価、定期などを使用することはできません。
task character(){
doLast{
def name = '张三'
def address ="北京市"
def age = 19
println "单引号双引号都是字符串 name is ${name}; age is $age ; address is ${address}"
println '单引号里无法运算表达式例如 name is ${name}'
}
}
実行文字
gradle character
次のように得られた結果であります
单引号双引号都是字符串 name is 张三; age is 19 ; address is 北京市
单引号里无法运算表达式例如 name is ${name}
唯一の変数は中括弧を省略することができれば、$ {}の式:二重引用符で囲まれた文字列が直接ルールは、中括弧が続くドル記号で、式を計算することができます。このような上記の$年齢など
セット
コレクションのデフォルトのタイプはjava.util.ArrayListのです
def nums = [1,2,4,5,6]
println "nums is ${nums.getClass().getName()} size = ${nums.size()}"
出力は、
nums is java.util.ArrayList size = 5
あなたは、キーワードとして使用されるタイプを指定明示的に設定することができます。
def nums1 = [0,"23",4,5,62,false] as LinkedList
println "nums1 is ${nums1.getClass().getName()};size = ${nums1.size()}"
出力
nums1 is java.util.LinkedList;size = 6
または明示的に前に型を指定します
LinkedList otherLinked = [3, 4, 5]
要素へのアクセス
アクセス要素は、インデックスを介してアクセスされています
println "第三个元素是 ${nums1[2]},倒数第一个是 ${nums1[-1]};第一个和倒数第一个:${nums1[0,-1]}"
println "第二个到第四个:${nums1[1..3]}"
出力は次のようになります。
第三个元素是 4,倒数第一个是 false;第一个和倒数第一个:[0, false]
第二个到第四个:[23, 4, 5]
横断要素
コレクションをデフォルトのパラメータにそれを使用して各メソッド
//遍历
nums1.each {
print "$it, "
}
出力は次のようになります。
0, 23, 4, 5, 62, false,
使用eachWithIndex方法:トラバースと件名の下で
numList.eachWithIndex { int value ,int index->
println "list[$index] = $value"
}
配列
指定された配列型の配列の定義をクリアするには
String [] strings = ["I","'","m","is","a","dog","."]
println "\n 数组 :${strings.getClass().getName()}"
strings.each{
print "$it "
}
def multi = [5,7,5,8,54,87] as int[]
println "\n使用 as 显式指定类型: ${multi.getClass().getName()}"
multi.each{
print "$it "
}
出力は、
数组 :[Ljava.lang.String;
I ' m is a dog .
使用 as 显式指定类型: [I
5 7 5 8 54 87
要素を追加します
要素を追加するList.add()を使用します
numList.add(-11)
使用して、<<演算子を追加するために使用することができます
numList << 13
要素を変更します。
numList[0] = 0
範囲外の添字を心配しないでください。Groovyは自動的に必要なインデックスに追加され、中盤はnullに設定されています
def numList = [0,1,2,3,4,5] as LinkedList
numList.each{
print "$it "
}
println "\n 在 10位置添加一个 11"
numList[10] =11
println "添加后的:"
numList.each{
print "$it "
}
出力は次のようになります。
> Task :collect1
0 1 2 3 4 5
在 10位置添加一个 11
添加后的:
0 1 2 3 4 5 null null null null 11
BUILD SUCCESSFUL in 0s
要素を削除します
インデックスパラメータを除去することができるされ、それが値であってもよいList.remove()要素を使用し
numList.remove 0
numList.remove((Object)10)
使用List.removeLastは()最後の要素を削除します
numList.removeLast()
検索要素
使用List.findは、()最初の予選要素を見つけます
print "\n list.find() 查找第一个符合条件的元素 numList.find { it%2==0}"
print numList.find { it%2==0}
すべての適格要素を探す)(List.findAllを使用します
print "\n list.findAll() 查找所有符合条件的元素 numList.findAll {it % 2 ==0 }"
print numList.findAll { it % 2 ==0}
List.any()があればtrueを返しに沿った要素があるように、要素を見つける使用
print "\n list.any() 只要有一个元素符合条件就返回 true numList.any { it % 2 ==1} "
print numList.any { it % 2 ==1}
真の使用List.everyは、要素を見つけるために)(返し、すべての要素が条件を遵守しなければならないだろう
print "\n list.every() 必须所有元素都符合条件才会返回 true numList.every {it % 2 == 0} "
print numList.every { it % 2 == 0}
統計的要素
統計的基準に沿った要素の数:List.countを(使用)
print numList.count { it % 2 ==0 }
統計的最大値:List.max()、最小:List.min()
print "\n 最大值是 ${numList.max()} ,最小值是 ${numList.min()}, 最小的绝对值是 "
print numList.min { Math.abs it}
地図
キーと値のペアのマップ方法を定義している、カンマ区切りを使用します
def colors = [red:'#FF0000',green:'#00FF00',blue:'#0000FF']
3つの方法でアクセスマップ要素:
- map.key
- マップ[キー]
- map.get(キー)
例えば:
task map{
doLast{
def colors = [red:'#FF0000',green:'#00FF00',blue:'#0000FF']
println " map calss is ${colors.getClass().getName()}"
println "通过 map.key 的方式访问 colors.red = ${colors.red}"
println "通过 map[key] 的方式访问 colors['red'] = ${colors['red']}"
println "通过 map.get(key) 的方式访问 colors.get(red) = ${colors.get('red')}"
}
}
出力は次のようになります。
> Task :map
map calss is java.util.LinkedHashMap
通过 map.key 的方式访问 colors.red = #FF0000
通过 map[key] 的方式访问 colors['red'] = #FF0000
通过 map.get(key) 的方式访问 colors.get(red) = #FF0000
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
要素を追加します
//添加元素
colors['pink'] = '#FF00FF'
colors.yellow = '#FFFF00'
要素を変更します。
//修改元素
colors.red = 'red'
colors['blue'] = 'blue'
println "修改后的元素是 colors.red = ${colors.red},colors.blue = ${colors.blue}"
要素を削除します
//删除元素
colors.remove('red')
横断要素
そして、上記のそれぞれに対して同じメソッドを使用します
//遍历
colors.each{
println "${it.key} :${it.value}"
}
検索要素
パラメータのMap.Entryやキー、値を上記のように、すべて同じ方法を探すが、交換してください。
ただ検索して例を作るために:
方法を見つけます
def green = colors.find { key ,value ->
if(key.equals('green')) {
return colors[key]
}
return null
}
println "查找结果是 ${green}"
def blue = colors.find { Map.Entry entry ->
if(entry.key.equals('blue')){
return entry.value
}
return null
}
println "查找的结果是 ${blue}"
方法
この方法は、defを使用して定義され
/*
* 返回大的那个
*/
def max(int a ,int b){
if(a>b){
return a
}else{
return b
}
}
リターンを省略することができます
Groovyの実行プロセスは、戻り値としてコードを続きます
/*
* 返回大的那个
*/
def max(int a ,int b){
if(a>b){
a
}else{
b
}
}
括弧を省略することができます。
括弧内のメソッドを省略してもよい呼び出す場合、パラメータは、スペースを離間させることができます
def printMaximum(int a,int b){
if(a>b){
println "The maximum value of $a and $b is $a"
}else{
println "The maximum value of $a and $b is $b"
}
}
task method {
doLast{
println "max is ${max(0,1)}"
printMaximum 10,20
}
}
出力は、
> Task :method
max is 1
The maximum value of 10 and 20 is 20
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
コードブロックは、パラメータとして渡されます
コードブロックは、実際に、クロージャ、括弧で囲まれたコードのセクションが費やされています。
例えば、各メソッド
最も原始的には次のようになります。
colors.each({println it})
フォーマット後
colors.each({
println it
})
最後のパラメータが所定のグルービー閉鎖され、閉鎖は外側法上に配置することができます
colors.each(){
println it
}
この方法は、括弧を省略することができたときに呼び出されるようになりましたさ
colors.each {
println it
}
クロージャ
クロージャはGroovyのの重要な機能ですDSLの基礎であると言うことができます。
実際にクロージャ、いくつかの無名ブロック。
クロージャは、変数またはフィールドに割り当てることができるように、それは、Groovyでクラスgroovy.lang.Closureクロージャの一例です。
クロージャの定義
def hello = { println "Hello 佛系编码" }
このクロージャを呼び出し
hello.call()
(保つために背中の上に直接呼び出すための別の方法)
hello()
シミュレーションを行った各下、反復された方法で指定された要素
/*
* closure 就是 闭包参数
*/
def customEach(closure){
//迭代元素
for(int i in 1..10){
//在闭包后跟上 () 就是调用了 括号里的参数就是闭包要接收的参数
closure(i)
}
}
閉鎖プリント要素を渡し、このメソッドを呼び出して、閉鎖が唯一のパラメータである場合、デフォルトではそれということです
// 如果只有一个参数 默认就是 it
customEach {
println it
}
>別のパラメータと本体 - クロージャは、複数のパラメータを受信する場合、パラメータが明示的に使用して、リストされなければなりません
再び反復シミュレーションのマップ:
def eachMap(closure){
def map1 = [name:'佛系编码',age:666]
map1.each {
closure(it.key,it.value)
}
}
·····
//如果有多个参数,就必须要把参数列出来,使用 -> 将 参数和主体分开
eachMap { key,value ->
println "$key:$value"
}
クロージャー委員会
Groovyのクロージャの力は、それが閉鎖方法を委任サポートしていることです。
Groovyのクロージャは三つの重要な属性を持っています
- thisObjectはクロージャはどこのクラスを定義します
- 所有者の閉鎖は、オブジェクトを定義または閉鎖(又は閉鎖クロージャ内で定義することができる)される場合、これは最近原理で表し、以下の説明は、尽くします
- デフォルトと同じ所有者の委任、手動で変更することができます。
クロージャはクラスで定義されている場合、デフォルトの属性は3に等しいです。
たとえば:閉鎖行為のPersonクラスを定義します
class Person{
private String name
public int getAge(){
12
}
Closure act ={
println "thisObject:${thisObject.getClass()}"
println "owner:${owner.getClass()}"
println "delegate:${delegate.getClass()}"
}
}
このクロージャを呼び出し、次のような出力があるでしょう
> Task :test
thisObject:class Person
owner:class Person
delegate:class Person
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
クロージャが閉袋に定義され、クラス定義のように他の二つのthisOjbectで同じでない場合でthisObject閉鎖が配置されて示され、そして閉鎖所有者クラスまたは表します
この時、閉じた袋で、その後は閉鎖外観を設定します
class Person{
private String name
public int getAge(){
12
}
Closure act ={
println "thisObject:$thisObject"
println "owner:$owner"
println "delegate:$delegate"
}
Closure eat = {
def test = {
println "thisObject:${thisObject.getClass()}"
println "owner:${owner.getClass()}"
println "delegate:${delegate.getClass()}"
}
test()
}
}
このクロージャの実装を食べるには、次の結果が得られます
> Task :test
thisObject:class Person
owner:class Person$_closure2
delegate:class Person$_closure2
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
thisObjectは、所有者が見ると同じではない持っている、それがでthisObjectが表現クラスであるため、所有者または閉鎖(最近の原則)クラス定義を表現することができます
3つのプロパティはすでにそれを理解し、
委任ポリシー
そこプロパティへのアクセスがあるか閉鎖でメソッドを呼び出すたびに、オブジェクトを明示的に設定されていない場合、それは委任ポリシーを呼び出します。アクセスプロパティやメソッドのコールかどうかを判断するには、この委任方針を通じ。
閉鎖のプロパティを変更することができ、いくつかの戦略があります。resolveStrategy
- Closure.OWNER_FIRSTデフォルトのポリシー、所有者のプロパティとメソッドのための最初の外観は、デリゲートで見つけることができません探しています。
- Closure.DELEGATE_FIRST最初のデリゲートで、その後、所有者に見て探していると、上記とは逆に、見つけることができません
- Closure.OWNER_ONLY所有者のみに見つけるため、無視デリゲート
- Closure.DELEGATE_ONLYのみ無視デリゲートに所有者を見つけるために
- Closure.TO_SELF高度なオプションは、開発者が自らの戦略を定義します
政策変更の実用化についての入れ子になったクラスのプレゼンテーションに従うこと。
二つの内部クラスとクラスの人足、およびname属性の両方を定義します。人の多老化特性。
class Person{
private String name
public int getAge(){
12
}
class Foot {
String name
Closure walk = { it ->
println "name is $name,age is $age ,delegate is ${delegate.getClass()}"
//设置 delegate 属性
delegate = it;
resolveStrategy = Closure.DELEGATE_FIRST
println "修改策略为 Closure.DELEGATE_FIRST delegate 优先"
println "name is $name, age is $age ,delegate is ${delegate.getClass()}"
}
}
void walk(){
Foot foot = new Foot(name:'脚');
foot.walk(this)
}
}
散歩の方法は人を呼び出します
Person person = new Person()
person.name ="佛系编码"
person.walk()
あなたは、次のような出力が得られます
> Task :test
name is 脚,age is 12 ,delegate is class Person$Foot
修改策略为 Closure.DELEGATE_FIRST delegate 优先
name is 佛系编码, age is 12 ,delegate is class Person
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
私はこの出力を説明しましょう
最初の名前は足であり、当然の所有者は、足で、デフォルトの戦略はClosure.OWNER_FIRSTが所有者の不動産を探しているためです。
2番目の名前は仏の符号化方式であり、ポリシーがClousre.DELEGATE_FIRST優先度に変更されたため、これは彼の値が明示的に仏に上記のシステムに記載されている、で渡すデリゲートに見つけることが、デリゲートの属性変更Personインスタンスコーディング。
年齢は唯一の人でgetAge()メソッドを宣言し、はっきりので12に戻ってポリシーを変更した場合でも、デリゲートの値のために、まだ12です。
注意:デリゲートのプロパティでのみ3つのプロパティを変更することができます。
クロージャは、それを構成することができるようにGradleではでは、我々は一般的に、現在のデリゲートを指定します
Userクラスを定義します。
class User{
String name
int age
def dumpUser(){
println "name is $name,age is $age ."
}
}
設定スクリプトを構築する上で定義された方法で、閉鎖Userクラスを設定するためにパラメータを渡します
閉鎖手数料ポリシーの変更、およびデリゲートのプロパティを設定します
def user(Closure<User> closure){
User user = new User()
closure.delegate = user
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure(user)
}
使用中に、例えば、我々は、タスクを作成したときなどで、Gradleではこのような多くは、DSL構成であります
task configClosure(){
doLast{
user {
name = '佛系编码'
age = 0
dumpUser()
}
}
}
出力
> Task :configClosure
name is 佛系编码,age is 0 .
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
カテゴリ
ここだけJavaと異なる場所インチ
コードの一部を見てください:
task obj{
doLast{
Person p = new Person()
println "没赋值前的 :${p.name}"
p.name = '佛系编码'
println "赋值后的 :${p.name}"
println "age is ${p.age}"
}
}
class Person{
private String name
public int getAge(){
12
}
}
タスクの出力OBJ行います
Task :obj
没赋值前的 :null
赋值后的 :佛系编码
age is 12
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
Personクラス名属性が定義されていない/ setメソッドを取得します。それは、その値を設定し、変更することができます。
Groovyのは、get / setメソッドを取得し、私たちを助けるためにするためです。
年齢プロパティを使用することができる唯一のgetAge()メソッドを定義し、Personクラスを定義しますが、年齢プロパティはありません。
しかし、この方法の決まった定義が存在しないため、その年齢は、専用のプロパティにアクセスすることができます。
演算子
ここでは、唯一のJavaと異なる事業者にして、一般的に
航空事業者かもしれません
非ヌル対象物自体を使用する場合、指定されたオブジェクトの値は空である。一般に、所与の変数のデフォルト値で使用し、空であってもよいです。
task operator {
doLast{
Person person = new Person();
//person.name 为 null 所以会使用 佛系编码
def name = person.name ? person.name:'佛系编码'
// getAge 返回 12 不为空 所以使用本身
def age = person.age ?:10
println "name is $name , age is $age"
}
}
輸出
> Task :operator
name is 佛系编码 , age is 12
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
オペレータの安全航行
オブジェクトが空の場合、それは空の例外がスローされますオブジェクトが空のときにオブジェクトのプロパティやメソッドの呼び出しは、この?。演算子の使用は、式の値が空の場合、それは例外をスローしません。 。
task operator {
doLast{
User user
println "user.name is ${user?.name}"
}
}
出力は、
> Task :operator
user.name is null
BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed
断言
アサーションは、仮定を検証するために使用されている条件が真ではないと仮定すると、Groovyのアサーションでは、真である、それはにjava.lang.AssertionError例外がスローされます。
GroovyとJavaのアサーションアサーションは完全に異なっています。Groovyは、アサーション言語機能でオンになっていると、JVMのアサーション-EA全く無関係。だから、私たちのユニットテストの好ましい方法です。
例えば
assert 1==2 :"1不等于2"
これは、次の例外がスローされます
FAILURE: Build failed with an exception.
······
* What went wrong:
Execution failed for task ':operator'.
> 1不等于2. Expression: (1 == 2)
もちろん、可能なメッセージが与えられていません
assert 1==2
だから、これは例外です。
Execution failed for task ':operator'.
> assert 1==2
|
false
アサーションを使用してメッセージを与えることが最良である場合は、このメッセージは、あなたの意図を明確に、あなたのコードを理解し、維持するために他人を助けることができます。
GroovyのAPIクエリ
クロージャのパラメータについては、唯一のクエリAPIは、良い方法はありません。
ここではGroovyのドキュメントリストされているアドレスは、関連するAPIを容易にするために、
取扱説明書
Gradleのか./gradleまたはgradlewコマンドを使用するには、もちろん、Gradleのも可能ディレクトリにインストールし、Gradleの環境変数をオフに設定する必要があります。
build.gradleが実行Gradleのコマンドは、現在のデフォルト・ディレクトリのbuild.gradleファイルで見つけるときに、デフォルトのGradleスクリプトファイルを、構築しています。
また、-b負荷パラメータで指定したファイルに対して実行することができます。
例えば、ここでオペレータのタスクを実行するgroovu-basic.build
gradle -b groovy-basic.gradle operator
コードは、上記のテストを実行する場合、ステップ
- 新しいファイルを作成するか、このGradleのを読んだことで、新しいプロジェクトを作成しますBuild.grale
- タスクを定義し、アクションを追加
task test{
doLast{
//这里是代码
}
}
- コードを貼り付けます。
- 実行タスク
gradle test
私はGradleのバージョンを囲みます