的Groovy將靜態構造函數來滿足這個初始化。看看下面的類:
import org.slf4j.Logger
import org.slf4j.LoggerFactory
class ClassWithLog {
protected static final Logger LOG = LoggerFactory.getLogger(this.getClass())
static void main(String[] args) {
LOG.info("Hello, world!")
}
}
讓我們把它編譯於.class
文件:
groovyc -cp ~/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar ClassWithLog.groovy
現在讓我們來看看字節碼是什麼樣的使用javap
命令:
javap -l -c ClassWithLog
我會跳過所有不相關的東西,直接去:(完整列表可以在這裏找到:https://gist.github.com/wololock/8d5a7cd049ef69a0d67567142e25b449)
static {};
Code:
0: invokestatic #23 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
3: ldc #89 // int 1
5: aaload
6: ldc #91 // class org/slf4j/LoggerFactory
8: invokestatic #23 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
11: ldc #92 // int 2
13: aaload
14: ldc #2 // class ClassWithLog
16: invokeinterface #96, 2 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callStatic:(Ljava/lang/Class;)Ljava/lang/Object;
21: invokeinterface #44, 3 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.call:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
26: astore_0
27: aload_0
28: ldc #98 // class org/slf4j/Logger
30: invokestatic #102 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
33: checkcast #98 // class org/slf4j/Logger
36: putstatic #36 // Field LOG:Lorg/slf4j/Logger;
39: aload_0
40: pop
41: return
LineNumberTable:
line 6: 0
正如你可以列出的字節碼看,Groovy中添加靜態構造函數(我們還沒有定義之一),它代替this.getClass()
在靜態情況下使用什麼時候invokestatic
。
如果我們從這個典型的Groovy類中刪除第6行,然後將它編譯成字節碼,靜態構造函數就不再存在了。去除靜態日誌後場
完整的字節碼列表:https://gist.github.com/wololock/ad0284a0065166585dcba6a3db1475dc
奇怪,如果這個工程(我沒有調查字節碼現在的時間)。請注意,'@ Slf4j'(或'@ Log4j',如果您使用傳統記錄器)AST通常更簡單。 – chrylis
或者它可以分開聲明和分配... –