2017-08-07 57 views
1

在java中:這VS靜在Groovy

protected static final Logger LOG = LoggerFactory.getLogger(this.getClass()) 

是不允許的,因爲這意味着我們試圖從靜態上下文訪問非靜態成員。

但Groovy允許使用同一段代碼。它將如何解決?

難道優先靜態從而使代碼看起來像:

protected static final Logger LOG = LoggerFactory.getLogger(MyClass.class) 

或將其非靜態參考放在優先位置,使代碼的樣子:

protected final Logger LOG = LoggerFactory.getLogger(this.getClass()) 
+0

奇怪,如果這個工程(我沒有調查字節碼現在的時間)。請注意,'@ Slf4j'(或'@ Log4j',如果您使用傳統記錄器)AST通常更簡單。 – chrylis

+1

或者它可以分開聲明和分配... –

回答

3

的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