78

このスレッドでは Groovy が忘れられているようですので、Groovy についても同じ質問をします。

  • Groovyコアへの回答を制限してみてください
  • 回答ごとに 1 つの機能
  • ドキュメントへのリンクだけでなく、機能の例と簡単な説明を提供してください
  • 最初の行として太字のタイトルを使用してフィーチャにラベルを付けます

以下も参照してください。

  1. Python の隠れた機能
  2. Ruby の隠れた機能
  3. Perl の隠れた機能
  4. Java の隠れた機能
4

31 に答える 31

56

スプレッドドット演算子の使用

def animals = ['ant', 'buffalo', 'canary', 'dog']
assert animals.size() == 4
assert animals*.size() == [3, 7, 6, 3]

これはのショートカットですanimals.collect { it.size() }

于 2008-11-19T22:31:41.950 に答える
39

withメソッドを使用すると、これを次のように変更できます。

 myObj1.setValue(10)
 otherObj.setTitle(myObj1.getName())
 myObj1.setMode(Obj1.MODE_NORMAL)

これに

 myObj1.with {
    value = 10
    otherObj.title = name
    mode = MODE_NORMAL
 }
于 2008-11-20T11:54:38.787 に答える
37

疑似オブジェクトとしてハッシュを使用する。

def x = [foo:1, bar:{-> println "Hello, world!"}]
x.foo
x.bar()

ダックタイピングと組み合わせると、このアプローチで長い道のりを進むことができます。「as」演算子を削除する必要はありません。

于 2008-11-19T22:07:37.660 に答える
37

エルビスについて知っている人はいますか?

def d = "hello";
def obj = null;

def obj2 = obj ?: d;   // sets obj2 to default
obj = "world"

def obj3 = obj ?: d;  // sets obj3 to obj (since it's non-null)
于 2008-11-20T03:55:20.203 に答える
35

オブジェクトにあるメソッドを見つけるのは、metaClass に尋ねるのと同じくらい簡単です。

"foo".metaClass.methods.name.sort().unique()

プリント:

["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo",
 "compareToIgnoreCase", "concat", "contains", "contentEquals", "copyValueOf", 
 "endsWith", "equals", "equalsIgnoreCase", "format", "getBytes", "getChars", 
 "getClass", "hashCode", "indexOf", "intern", "lastIndexOf", "length", "matches", 
 "notify", "notifyAll", "offsetByCodePoints", "regionMatches", "replace", 
 "replaceAll", "replaceFirst", "split", "startsWith", "subSequence", "substring", 
 "toCharArray", "toLowerCase", "toString", "toUpperCase", "trim", "valueOf", "wait"]
于 2008-11-21T05:52:05.570 に答える
28

欠落している静的メソッドをインターセプトするには、次を使用します

 Foo {
    static A() { println "I'm A"}

     static $static_methodMissing(String name, args) {
        println "Missing static $name"
     }
 }

Foo.A()  //prints "I'm A"
Foo.B()  //prints "Missing static B"

-ケン

于 2010-08-31T01:28:12.327 に答える
24

破壊

Groovy では別の名前で呼ばれている可能性があります。これは、clojure では破壊と呼ばれます。信じられないほど便利です。

def list = [1, 'bla', false]
def (num, str, bool) = list
assert num == 1
assert str == 'bla'
assert !bool
于 2012-10-04T14:10:03.367 に答える
21

groovy で Java コードをテストする場合、オブジェクト グラフ ビルダーは驚くべきものです。

def company = builder.company( name: 'ACME' ) {
   address( id: 'a1', line1: '123 Groovy Rd', zip: 12345, state: 'JV' )
   employee(  name: 'Duke', employeeId: 1 ){
      address( refId: 'a1' )
   }
}

標準機能ですが、それでも本当に素晴らしいです。

ObjectGraphBuilder

(ビルダーサポートが機能するのListではなく、空のリストのデフォルト値であるPOJO のプロパティを指定する必要があります。)null

于 2008-11-20T07:13:38.807 に答える
19
println 
"""
Groovy has "multi-line" strings.
Hooray!
"""
于 2008-11-20T18:43:05.887 に答える
15

宇宙船オペレーターの使用

私はSpaceship operatorが好きで、あらゆる種類のカスタム ソート シナリオに役立ちます。使用例をいくつかここに示します。これが特に役立つ状況の 1 つは、複数のフィールドを使用してオブジェクトの実行中にコンパレーターを作成する場合です。例えば

def list = [
    [ id:0, first: 'Michael', last: 'Smith', age: 23 ],
    [ id:1, first: 'John', last: 'Smith', age: 30 ],
    [ id:2, first: 'Michael', last: 'Smith', age: 15 ],    
    [ id:3, first: 'Michael', last: 'Jones', age: 15 ],   
]

// sort list by last name, then first name, then by descending age
assert (list.sort { a,b -> a.last <=> b.last ?: a.first <=> b.first ?: b.age <=> a.age })*.id == [ 3,1,0,2 ]
于 2011-08-09T17:19:09.053 に答える
15

Java とは異なり、Groovy では、プリミティブ型だけでなく、あらゆるものをswitchステートメントで使用できます。一般的なイベントで実行されるメソッド

switch(event.source) {
   case object1:
        // do something
        break
   case object2:
        // do something
        break
}
于 2008-11-20T11:46:24.777 に答える
15

Groovy 1.6 では、正規表現はすべてのクロージャ イテレータ (each、collect、inject など) で機能し、キャプチャ グループを簡単に操作できます。

def filePaths = """
/tmp/file.txt
/usr/bin/dummy.txt
"""

assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file -> 
        "$file -> $path"
    } ==  ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
于 2008-11-21T05:47:41.273 に答える
14

クロージャーは、リソース管理の古い試行錯誤のゲームをすべてなくすことができます。ファイル ストリームは、ブロックの最後で自動的に閉じられます。

new File("/etc/profile").withReader { r ->
    System.out << r
}
于 2008-11-20T18:56:02.960 に答える
13

次のような、GDK のgroovy.transformパッケージ内の変換によって提供される機能:

  • @Immutable: @Immutable アノテーションは、必要なゲッター、コンストラクター、equals、hashCode およびその他のヘルパー メソッドを追加する AST 変換を実行するようコンパイラーに指示します。これらのヘルパー メソッドは、定義されたプロパティを持つ不変クラスを作成するときに通常記述されます。
  • @CompileStatic: これにより、Groovy コンパイラは Java スタイルのコンパイル時チェックを使用して静的コンパイルを実行できるようになり、Groovy メタ オブジェクト プロトコルがバイパスされます。
  • @Canonical: @Canonical アノテーションは、位置コンストラクター、equals、hashCode、およびプリティ プリント toString をクラスに追加する AST 変換を実行するようコンパイラーに指示します。

その他:

  • @Slf4jこのローカル変換は、LogBack ロギングを使用してプログラムにロギング機能を追加します。log という名前のバインドされていない変数に対するすべてのメソッド呼び出しは、ロガーへの呼び出しにマップされます。
  • Groovy の XML Slurper : XML の簡単な解析。キラー機能!
于 2013-06-28T17:38:42.227 に答える
12

クロージャベースのインターフェイスの実装

次のような型指定された参照がある場合:

MyInterface foo

以下を使用して、インターフェース全体を実装できます。

foo = {Object[] args -> println "This closure will be called by ALL methods"} as MyInterface

または、各メソッドを個別に実装する場合は、次を使用できます。

foo = [bar: {-> println "bar invoked"}, 
    baz: {param1 -> println "baz invoked with param $param1"}] as MyInterface
于 2009-06-15T13:59:39.077 に答える
12

toSpreadMap() を使用してリストをマップに変換できます。これは、キーとそれに関連付けられた値を決定するのにリスト内の順序だけで十分な場合に便利です。以下の例を参照してください。

def list = ['key', 'value', 'foo', 'bar'] as Object[]
def map = list.toSpreadMap()

assert 2 == map.size()
assert 'value' == map.key
assert 'bar' == map['foo']
于 2010-09-17T21:32:46.920 に答える
8

nullリストから値を削除

def list = [obj1, obj2, null, obj4, null, obj6]
list -= null
assert list == [obj1, obj2, obj4, obj6]
于 2014-01-16T12:05:34.600 に答える
7

@デリゲート

class Foo {
    def footest() { return "footest"}   
}

class Bar {
    @Delegate Foo foo = new Foo()     
}

def bar = new Bar()

assert "footest" == bar.footest()
于 2013-11-16T17:17:42.437 に答える
5

暗黙の引数を使用した引数の並べ替えは、もう 1 つの優れた機能です。

このコード:

def foo(Map m=[:], String msg, int val, Closure c={}) {
  [...]
}

これらすべての異なるメソッドを作成します。

foo("msg", 2, x:1, y:2)
foo(x:1, y:2, "blah", 2)
foo("blah", x:1, 2, y:2) { [...] }
foo("blah", 2) { [...] }

もっと。名前付き引数と序数引数を間違った順序/位置に置いて台無しにすることは不可能です。

もちろん、"foo" の定義では、"String msg" と "int val" から "String" と "int" を省略できます。わかりやすくするために残しました。

于 2008-11-19T22:53:47.397 に答える
4

メソッド パラメータでスプレッド演算子を使用する

これは、コードをデータに変換する際に非常に役立ちます。

def exec(operand1,operand2,Closure op) {
    op.call(operand1,operand2)
}

def addition = {a,b->a+b}
def multiplication = {a,b->a*b}

def instructions = [
     [1,2,addition],
     [2,2,multiplication]
]

instructions.each{instr->
    println exec(*instr)
}

この使用法も役立ちます:

String locale="en_GB"

//this invokes new Locale('en','GB')
def enGB=new Locale(*locale.split('_'))
于 2013-03-08T13:57:26.423 に答える
3

メモ化

メモ化は、高価な関数呼び出しの結果を保存し、関数が同じ引数で再度呼び出されるたびにキャッシュされた結果を返すことからなる最適化手法です。

無制限のバージョンがあり、これまでに見た (入力引数、戻り値) のペアをキャッシュします。LRU キャッシュを使用して、最後に表示された N 個の入力引数とその結果をキャッシュする限定バージョン。

メソッドのメモ化:

import groovy.transform.Memoized

@Memoized
Number factorial(Number n) {
    n == 0 ? 1 : factorial(n - 1)
}

@Memoized(maxCacheSize=1000)
Map fooDetails(Foo foo) {
    // call expensive service here
}

クロージャのメモ化:

def factorial = {Number n ->
    n == 0 ? 1 : factorial(n - 1)
}.memoize()

fooDetails = {Foo foo ->
    // call expensive service here
}.memoizeAtMost(1000)

ウィキペディアのページには、コンピューター サイエンスにおけるメモ化の使用に関する広範な情報があります。簡単な実用的な使用方法を 1 つだけ指摘します。

定数の初期化を可能な限り最後まで延期する

クラスの定義時または作成時に初期化できない定数値がある場合があります。たとえば、定数式は、クラスの初期化後に別のもの (Spring など) によってプラグインされる別のクラスの別の定数またはメソッドを使用する場合があります。

この場合、定数をゲッターに変換して で装飾できます@Memoized。最初にアクセスされたときに一度だけ計算され、その後値がキャッシュされて再利用されます。

import groovy.transform.Memoized

@Memoized
def getMY_CONSTANT() {
    // compute the constant value using any external services needed
}
于 2015-05-06T10:32:09.210 に答える
2

安全運航事業者

安全なナビゲーション演算子は、NullPointerException を回避するために使用されます。通常、オブジェクトへの参照がある場合、オブジェクトのメソッドまたはプロパティにアクセスする前に、それが null でないことを確認する必要がある場合があります。これを回避するために、セーフ ナビゲーション オペレータは次のように、例外をスローする代わりに単純に null を返します。

def person = Person.find { it.id == 123 }        // find will return a null instance    
def name = person?.name                          // use of the null-safe operator prevents from a NullPointerException, result is null
于 2015-04-13T12:28:48.080 に答える
2

groovy で数行で JSON ツリーを構築する方法は?

1)自己参照withDefaultクロージャーでツリーを定義します

def tree // declare  first before using a self reference
tree = { ->  [:].withDefault{ tree() } }

2) 独自の JSON ツリーを作成する

frameworks = tree()
frameworks.grails.language.name = 'groovy'
frameworks.node.language.name = 'js'

def result =  new groovy.json.JsonBuilder(frameworks)

これにより、次のことが得られます。{"grails":{"language":{"name":"groovy"}},"node":{"language":{"name":"js"}}}

于 2014-03-23T19:10:51.200 に答える
2

Groovy can work a lot like Javascript. You can have private vars and functions via closure. You can also curry functions with closures.

class FunctionTests {

def privateAccessWithClosure = {

    def privVar = 'foo'

    def privateFunc = { x -> println "${privVar} ${x}"}

    return {x -> privateFunc(x) } 
}


def addTogether = { x, y ->
    return x + y
}

def curryAdd = { x ->
    return { y-> addTogether(x,y)}
}

public static void main(String[] args) {
    def test = new FunctionTests()

    test.privateAccessWithClosure()('bar')

    def curried = test.curryAdd(5)

    println curried(5)
}
}

output:

foo bar 10

于 2012-11-20T09:34:54.520 に答える