The major difference is the MOP (Meta Object Protocol): @TypeChecked
keep methods going through the MOP, while @CompileStatic
generate method calls similar to Java's bytecode. This means their semantic are different, but it also means you can still apply metaprogramming on top of a @TypeChecked
code, as long as the method call can be resolved at compile time.
The following code shows the MOP acting on a @TypeChecked
code, and not on @CompileStatic
code:
import groovy.transform.CompileStatic as CS
import groovy.transform.TypeChecked as TC
class Foo {
def bar = "bar"
}
class TestTC {
Foo foo
TestTC() {
foo = new Foo()
foo.metaClass.getBar = { "metaClass'd bar" }
}
@TC
def typed() {
foo.bar
}
@CS
def compiled() {
foo.bar
}
}
assert new TestTC().typed() == "metaClass'd bar"
assert new TestTC().compiled() == "bar"
For @CompileStatic
, yes, Groovy tries to generate bytecode close to what javac
would output, thus, their performance are very close, with a few exceptions.
(Updated 2016-01-13)
Both @CompileStatic
and @TypeChecked
will allow:
- Closures (including Closure delegations through
@DelegatesTo
);
- ASTs (which can be used for compile-time metaprogramming);
- Groovy's syntatic sugar, like those on regex, lists, maps, operator overload and the likes;
- Extensions.
For @TypeChecked
, you can also instruct the compiler to ignore some type checks through a Type Checking Extensions, allowing more flexibility. @CompileStatic
also support this, but is a little more restrictive.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…