Reputation: 446
In java:
protected static final Logger LOG = LoggerFactory.getLogger(this.getClass())
is not allowed as this would mean that we are trying to access non static member from a static context.
However Groovy allows same piece of code. How would it be resolved?
Would it give priority to static thus making the code to look like:
protected static final Logger LOG = LoggerFactory.getLogger(MyClass.class)
or would it give priority to non static reference and make code look like:
protected final Logger LOG = LoggerFactory.getLogger(this.getClass())
Upvotes: 1
Views: 2916
Reputation: 42184
Groovy adds static constructor to satisfy this initialization. Take a look at following class:
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!")
}
}
Let's compile it to the .class
file:
groovyc -cp ~/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar ClassWithLog.groovy
And now let's take a look what the bytecode looks like using javap
command:
javap -l -c ClassWithLog
I will skip all unrelated stuff and go directly to: (full listing can be found here: 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
As you can see in the bytecode listed, Groovy added a static constructor (we haven't defined one) and it did invokestatic
in place of this.getClass()
when used in the static context.
If we remove line 6 from this exemplary Groovy class and then compile it to the bytecode, static constructor does not exist any more.
Full bytecode listing after removing static LOG field: https://gist.github.com/wololock/ad0284a0065166585dcba6a3db1475dc
Upvotes: 3