A anotação @JvmSynthetic em Kotlin
1. Introdução
Kotlin is a programming language for the JVM and compiles directly to Java Bytecode. No entanto, é muito mais conciso do que Java, e certos recursos JVM não se encaixam diretamente na linguagem.
Em vez disso,Kotlin provides a set of annotations that we can apply to our code to trigger these features. Todos eles existem no pacotekotlin.jvm emkotlin-stdlib.
Um dos mais esotéricos deles é a anotação@JvmSynthetic.
2. O que@JvmSynthetic faz?
Esta anotação é aplicável a métodos, campos, getters e setters - e émarks the appropriate element as synthetic in the generated class file.
Podemos usar esta anotação em nosso código exatamente da mesma forma que qualquer outra anotação:
@JvmSynthetic
val syntheticField: String = "Field"
var syntheticAccessor: String
@JvmSynthetic
get() = "Accessor"
@JvmSynthetic
set(value) {
}
@JvmSynthetic
fun syntheticMethod() {
}
Quando o código acima é compilado,the compiler assigns the ACC_SYNTHETIC attribute to the corresponding elements in the class file:
private final java.lang.String syntheticField;
descriptor: Ljava/lang/String;
flags: ACC_PRIVATE, ACC_FINAL, ACC_SYNTHETIC
ConstantValue: String Field
RuntimeInvisibleAnnotations:
0: #9()
public final void syntheticMethod();
descriptor: ()V
flags: ACC_PUBLIC, ACC_FINAL, ACC_SYNTHETIC
Code:
stack=0, locals=1, args_size=1
0: return
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Lcom/example/kotlin/SyntheticTest;
LineNumberTable:
line 20: 0
3. Qual é o atributo sintético?
The ACC_SYNTHETIC attribute is intended by the JVM Bytecode to indicate that an element wasn’t actually present in the original source code, mas foi gerado pelo compilador.
Sua intenção original era oferecer suporte a classes e interfaces aninhadas no Java 1.1, mas agora podemos aplicá-lo a qualquer elemento que for necessário.
Any element that the compiler marks as synthetic will be inaccessible from the Java language. Isso inclui não estar visível em nenhuma ferramenta, como nosso IDE. No entanto, nosso código Kotlin não possui essas restrições e pode ver e acessar esses elementos perfeitamente.
Observe que se tivermos um campo Kotlin anotado com@JvmSynthetic, mas não anotado com@JvmField,, o getter e o setter gerados não são considerados métodos sintéticos e podem ser acessados perfeitamente.
Podemos acessar elementos sintéticos de Java usando a API de reflexão se formos capazes de localizá-los - por exemplo, por nome:
Method syntheticMethod = SyntheticClass.class.getMethod("syntheticMethod");
syntheticMethod.invoke(syntheticClass);
4. Para que posso usar isso?
Os únicos benefícios reais disso são ocultar o código dos desenvolvedores e ferramentas Java e como uma indicação para outros desenvolvedores quanto ao estado do código. It’s intended for working at a much lower level than most typical application code.
The intention of it is to support code generation, permitindo que o compilador gere campos e métodos que não devem ser expostos a outros desenvolvedores, mas que são necessários para suportar a interface exposta real. Podemos pensar nisso como um nível de proteção além deprivate ouinternal.
Como alternativa, podemos usá-lo para ocultar o código de outras ferramentas,, como cobertura de código ou análise estática.
No entanto, não há garantia de que qualquer ferramenta honrará este sinalizador, por isso pode nem sempre ser útil aqui.
5. Conclusão
A anotação@JvmSynthetic pode não ser a ferramenta mais útil disponível, mas tem usos em certas situações, como vimos aqui.
Como sempre, mesmo que raramente o possamos usar, outra ferramenta disponível na caixa de ferramentas do desenvolvedor pode ser bastante benéfica. Quando chegar a hora de você precisar dessa ferramenta, vale a pena saber como ela funciona.