@JvmSynthetic 在 Kotlin 中的用途是什么? [英] What's the intended use of @JvmSynthetic in Kotlin?

查看:24
本文介绍了@JvmSynthetic 在 Kotlin 中的用途是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了@JvmSynthetic 注释,我想知道它的用途,但不幸的是,它没有记录.(UPD:那一刻)

I have come across the @JvmSynthetic annotation in kotlin-stdlib, and I'm wondering what it is for, but, unfortunately, it is undocumented. (UPD: it was at that moment)

据我所知,将其应用于程序元素会将 synthetic 修饰符添加到相应的字节码元素.结果,该元素在 Java 中变得不可见:

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() { }
}

Java 代码中的某处:

Somewhere in Java code:

MyClass c = new MyClass();
c.f() // Error: cannot resolve method f()

但是相同的元素在 Kotlin 代码中仍然可见:

But the same elements are still visible in Kotlin code:

val c = MyClass()
c.f() // OK

从非 Kotlin 来源隐藏声明是否有效使用 @JvmSynthetic?它是预期用途吗?其他合适的用例是什么?

Is hiding declarations from non-Kotlin sources a valid use of @JvmSynthetic? Is it the intended use? What are the other appropriate use cases?

由于 @JvmSynthetic 对 Java 隐藏了函数,它们也不能在 Java 中被覆盖(并且当涉及到 abstract 成员时,调用结果为 抽象方法错误).鉴于此,我可以使用 @JvmSynthetic 来禁止覆盖 Java 源代码中 Kotlin 类的成员吗?

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?

推荐答案

首先,要回答实际上是什么合成方法,让我们来看看Java 语言规范:

First, to answer what synthetic methods actually are, let's have a look at the Java language specification:

11. 如果 Java 编译器发出的构造与源代码中显式或隐式声明的构造不对应,则必须将其标记为合成,除非发出的构造构造是一个类初始化方法(JVMS §2.9).

11. A construct emitted by a Java compiler must be marked as synthetic if it does not correspond to a construct declared explicitly or implicitly in source code, unless the emitted construct is a class initialization method (JVMS §2.9).

@JvmSynthetic 注释正是这样做的:防止从源代码访问.该方法仍会出现在反射中,然后被标记为合成.

The @JvmSynthetic annotation does exactly that: prevent access from source code. The method will still appear in reflection and is then marked as synthetic.

更准确地说,来自Kotlin 文档(强调我的):

More precisely, from the Kotlin documentation (emphasis mine):

在 Java 字节码中的注释目标上设置 ACC_SYNTHETIC 标志.

@JvmSynthetic

Sets ACC_SYNTHETIC flag on the annotated target in the Java bytecode.

在编译时 Java 源无法访问合成目标,而 Kotlin 源仍然可以访问. 将目标标记为合成是二进制兼容的更改,已编译的 Java 代码将能够访问此类目标.

Synthetic targets become inaccessible for Java sources at compile time while still being accessible for Kotlin sources. Marking target as synthetic is a binary compatible change, already compiled Java code will be able to access such target.

此注释适用于罕见的情况,即 API 设计人员需要对 Java API 隐藏 Kotlin 特定目标,同时将其保留为 Kotlin API 的一部分,因此生成的 API 对两者都是惯用的.

This annotation is intended for rare cases when API designer needs to hide Kotlin-specific target from Java API while keeping it a part of Kotlin API so the resulting API is idiomatic for both.

如上一段所述,@JvmSynthetic 是一种 API 设计工具,可让库编写者避免自动生成 Java 等效项.最流行的用例可能是 Kotlin 独有的特性,例如运算符重载、componentN() 方法或属性,它们可能有更惯用的方式在 Java 中公开.

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.

值得注意的是,这个注解的对象是属性设置器/获取器、函数和字段——基本上是所有在 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.

@Target([
    AnnotationTarget.FUNCTION,
    AnnotationTarget.PROPERTY_GETTER,
    AnnotationTarget.PROPERTY_SETTER,
    AnnotationTarget.FIELD])
annotation actual class JvmSynthetic

这篇关于@JvmSynthetic 在 Kotlin 中的用途是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆