I have come across the @JvmSynthetic
annotation in kotlin-stdlib, and I'm wondering what it is for, but, unfortunately, it is undocumented.
As far as I understand, applying it to a program element will add the synthetic
modifier to the corresponding bytecode elements. As a consequence, the element becomes invisible from Java:
class MyClass {
@JvmSynthetic
fun f() { }
}
Somewhere in Java code:
MyClass c = new MyClass();
c.f() // Error: cannot resolve method f()
But the same elements are still visible in Kotlin code:
val c = MyClass()
c.f() // OK
Is hiding declarations from non-Kotlin sources a valid use of @JvmSynthetic
? Is it the intended use? What are the other appropriate use cases?
Since @JvmSynthetic
hides functions from Java, they cannot be overridden in Java either (and when it comes to an abstract
member, the calls then result into AbstractMethodError
). Given that, can I use @JvmSynthetic
to prohibit overriding members of a Kotlin class in Java sources?
In plain Java,
synthetic
methods are generated by thejavac
compiler. Normally the compiler must create synthetic methods on nested classes, when fields specified with the private modifier are accessed by the enclosing class.Given the following class in java:
when the
SyntheticSample
class accesses thenested.syntheticString
field, it is indeed calling a staticsynthetic
method generated by the compiler (named something likeaccess$100
).Even if Kotlin exposes a
@JvmSynthetic
annotation that is able to "force" the creation of synthetic methods, I advice to not using it in normal "user" code. Synthetic methods are low-level tricks made by the compiler, and we should never rely on such things in everyday code. I think it's there to support other parts of the standard library, but you should ask the JetBrains guys directly if you're curious (try on the official Kotlin Discussion Forum)First, to answer what synthetic methods actually are, let's have a look at the Java language specification:
The
@JvmSynthetic
annotation does exactly that: prevent access from source code. The method will still appear in reflection and is then marked as synthetic.More precisely, from the Kotlin documentation (emphasis mine):
As described in the last paragraph,
@JvmSynthetic
is a tool for API design, which lets a library writer avoid automatic generation of Java equivalents. Probably the most popular use cases are Kotlin-only features, such as operator overloading,componentN()
methods or properties, which may have a more idiomatic way to be exposed in Java.It is noteworthy that the target of this annotations are property setters/getters, functions and fields -- basically everything that translates in Java to a method.