이 스레드에서 Groovy가 잊혀진 것 같아서 Groovy에 대해 동일한 질문을 할 것입니다.
- Groovy 코어에 대한 답변을 제한하십시오.
- 답변 당 하나의 기능
- 문서에 대한 링크뿐만 아니라 기능의 예와 간단한 설명을 제공합니다.
- 첫 번째 줄로 굵은 제목을 사용하여 지형지 물에 레이블 지정
또한보십시오:
이 스레드에서 Groovy가 잊혀진 것 같아서 Groovy에 대해 동일한 질문을 할 것입니다.
또한보십시오:
답변:
확산 점 연산자 사용
def animals = ['ant', 'buffalo', 'canary', 'dog']
assert animals.size() == 4
assert animals*.size() == [3, 7, 6, 3]
이것은의 바로 가기입니다 animals.collect { it.size() }
.
와 방법은이를 끌 수 있습니다 :
myObj1.setValue(10)
otherObj.setTitle(myObj1.getName())
myObj1.setMode(Obj1.MODE_NORMAL)
이것으로
myObj1.with {
value = 10
otherObj.title = name
mode = MODE_NORMAL
}
myObj1.value = 10
setter 메서드를 호출 할 필요가 없기 때문에 (등)과 후자 사이에 더 일반적인 비교 가되지 않을까요?
엘비스 에 대해 아는 사람 있나요?
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)
객체에 어떤 메소드가 있는지 알아내는 것은 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"]
누락 된 정적 메서드를 가로 채려면 다음을 사용하십시오.
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"
- 켄
구조화
Groovy에서는 다른 이름으로 불릴 수 있습니다. 클로저에서 구조화라고합니다. 얼마나 편리 할 수 있는지 결코 믿지 못할 것입니다.
def list = [1, 'bla', false]
def (num, str, bool) = list
assert num == 1
assert str == 'bla'
assert !bool
groovy로 자바 코드를 테스트 할 때 객체 그래프 빌더는 놀랍습니다.
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' )
}
}
표준 기능이지만 여전히 정말 좋습니다.
( 빌더 지원이 작동하는 List
대신 빈 목록의 기본값 인 POJO의 특성을 제공해야합니다 null
.)
println
"""
Groovy has "multi-line" strings.
Hooray!
"""
Groovy 1.6에서 정규 표현식은 모든 클로저 반복자 (각각, 수집, 주입 등)와 함께 작동하며 캡처 그룹으로 쉽게 작업 할 수 있습니다.
def filePaths = """
/tmp/file.txt
/usr/bin/dummy.txt
"""
assert (filePaths =~ /(.*)\/(.*)/).collect { full, path, file ->
"$file -> $path"
} == ["file.txt -> /tmp", "dummy.txt -> /usr/bin"]
Java와 달리 Groovy에서는 기본 유형뿐만 아니라 모든 것이 switch 문에 사용될 수 있습니다 . 일반적인 eventPerformed 메서드에서
switch(event.source) {
case object1:
// do something
break
case object2:
// do something
break
}
우주선 연산자 사용
모든 종류의 사용자 지정 정렬 시나리오에 유용한 우주선 연산자를 좋아합니다 . 여기에 몇 가지 사용 예가 있습니다 . 특히 도움이되는 한 가지 상황은 여러 필드를 사용하여 개체의 즉석에서 비교기를 만드는 것입니다. 예 :
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 ]
다음 groovy.transform
과 같은 GDK 패키지 내부의 변환에서 제공하는 기능 :
@Immutable
: @Immutable 주석은 정의 된 속성으로 불변 클래스를 만들 때 일반적으로 작성되는 필요한 getter, 생성자, equals, hashCode 및 기타 도우미 메서드를 추가하는 AST 변환을 실행하도록 컴파일러에 지시합니다.@CompileStatic
: 이렇게하면 Groovy 컴파일러가 Java 스타일의 컴파일 시간 검사를 사용한 다음 정적 컴파일을 수행하여 Groovy 메타 개체 프로토콜을 우회 할 수 있습니다.@Canonical
: @Canonical 어노테이션은 위치 생성자, 같음, hashCode 및 예쁜 인쇄 toString을 클래스에 추가하는 AST 변환을 실행하도록 컴파일러에 지시합니다.기타 :
@Slf4j
이 로컬 변환은 LogBack 로깅을 사용하여 프로그램에 로깅 기능을 추가합니다. log라는 이름의 바인딩되지 않은 변수에 대한 모든 메서드 호출은 로거 호출에 매핑됩니다.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']
as Object []
첫 번째 줄에 필요합니까?
클로저 기반 인터페이스 구현
다음과 같이 입력 된 참조가있는 경우 :
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
내가 조금 늦었다는 것을 알고 있지만 여기에 몇 가지 멋진 기능이 누락 된 것 같습니다.
컬렉션 플러스 / 마이너스 연산자
def l = [1, 2, 3] + [4, 5, 6] - [2, 5] - 3 + (7..9)
assert l == [1, 4, 6, 7, 8, 9]
def m = [a: 1, b: 2] + [c: 3] - [a: 1]
assert m == [b: 2, c: 3]
Switch 문
switch (42) {
case 0: .. break
case 1..9: .. break
case Float: .. break
case { it % 4 == 0 }: .. break
case ~/\d+/: .. break
}
범위 및 색인
assert (1..10).step(2) == [1, 3, 5, 7, 9]
assert (1..10)[1, 4..8] == [2, 5, 6, 7, 8, 9]
assert ('a'..'g')[-4..-2] == ['d', 'e', 'f']
유니 코드 변수 이름
def α = 123
def β = 456
def Ω = α * β
assert Ω == 56088
리터럴의 밑줄
긴 리터럴 숫자를 쓸 때, 예를 들어 수천 개의 단어 그룹과 같이 일부 숫자가 함께 그룹화되는 방식을 파악하기가 더 어렵습니다. 숫자 리터럴에 밑줄을 넣을 수있게함으로써 이러한 그룹을 쉽게 찾을 수 있습니다.
long creditCardNumber = 1234_5678_9012_3456L
long socialSecurityNumbers = 999_99_9999L
double monetaryAmount = 12_345_132.12
long hexBytes = 0xFF_EC_DE_5E
long hexWords = 0xFFEC_DE5E
long maxLong = 0x7fff_ffff_ffff_ffffL
long alsoMaxLong = 9_223_372_036_854_775_807L
long bytes = 0b11010010_01101001_10010100_10010010
암시 적 인수를 사용한 인수 재정렬은 또 다른 좋은 방법입니다.
이 코드 :
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"를 생략 할 수 있습니다. 명확성을 위해 그대로 두었습니다.
메서드 매개 변수에서 확산 연산자 사용
이것은 코드를 데이터로 변환 할 때 큰 도움이됩니다.
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('_'))
메모 화
Memoization은 값 비싼 함수 호출의 결과를 저장하고 동일한 인수로 함수가 다시 호출 될 때마다 캐시 된 결과를 반환하는 최적화 기술입니다.
무제한 버전이 있는데, 그것은 그것이 볼 수있는 (입력 인수, 반환 값) 쌍을 캐시합니다. 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)
Wikipedia 페이지 에는 컴퓨터 과학의 Memoization 사용에 대한 광범위한 정보가 있습니다. 나는 단지 하나의 간단한 실용적인 사용을 지적 할 것이다.
상수 초기화를 가능한 마지막 순간으로 연기
때로는 클래스 정의 또는 생성시 초기화 할 수없는 상수 값이 있습니다. 예를 들어 상수 표현식은 다른 상수 또는 다른 클래스의 메서드를 사용할 수 있으며, 클래스 초기화 후 다른 항목 (Spring 등)에 의해 연결됩니다.
이 경우 상수를 getter로 변환하고 @Memoized
. 처음 액세스 할 때 한 번만 계산 된 다음 값이 캐시되고 재사용됩니다.
import groovy.transform.Memoized
@Memoized
def getMY_CONSTANT() {
// compute the constant value using any external services needed
}
Groovy는 Javascript와 매우 유사하게 작동 할 수 있습니다. 클로저를 통해 개인 변수와 함수를 가질 수 있습니다. 클로저로 카레 기능을 사용할 수도 있습니다.
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)
}
}
산출:
푸 바 10
동적 메서드 호출
이름이있는 문자열을 사용하여 메소드를 호출 할 수 있습니다.
class Dynamic {
def one() { println "method one()" }
def two() { println "method two()" }
}
def callMethod( obj, methodName ) {
obj."$methodName"()
}
def dyn = new Dynamic()
callMethod( dyn, "one" ) //prints 'method one()'
callMethod( dyn, "two" ) //prints 'method two()'
dyn."one"() //prints 'method one()'
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"}}}
안전한 내비게이션 연산자
Safe Navigation 연산자는 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
1) 한 줄에 여러 변수 선언
def (a,b,c) = [1,2,3]
2) 다른 유형 선언 사용.
def (String a, int b) = ['Groovy', 1]
강제 연산자 (as)는 캐스팅의 변형입니다. Coercion은 할당에 호환되지 않고 객체를 한 유형에서 다른 유형으로 변환합니다. 예를 들어 보겠습니다.
Integer x = 123
String s = (String) x
Integer는 String에 할당 할
수 없으므로 런타임에 ClassCastException이 생성 됩니다. 대신 강제 변환을 사용하여 해결할 수 있습니다.
Integer x = 123 String s = x as String
Integer는 String에 할당 할 수 없지만 as를 사용하면 String으로 강제 변환됩니다.