@JvmDefaultWithoutCompatibility
@JvmDefaultWithCompatibility
使用
@JvmDefaultWithoutCompatibility
Used only with -Xjvm-default=all-compatibility
.
@JvmDefaultWithCompatibility
Used only with -Xjvm-default=all
.
区别
前置知识
当一个接口包含默认方法(在Kotlin中称为JVM默认方法),而其派生类在运行时未实现这些默认方法时,编译器会生成一个特殊的类,通常称为 DefaultImpls
,其中包含这些默认方法的实现。
在Kotlin中,兼容性访问器是一种机制,用于处理默认方法在接口中的实现。
以下是两种不同的生成方式:
-
不带兼容性访问器的类或接口:
- 在这种情况下,编译器生成的类或接口仅包含默认方法,而不会生成专门的访问器类(通常是
DefaultImpls
)来提供对这些默认方法的实现的访问。这意味着,如果派生类没有实现这些默认方法,可能会在运行时出现问题,因为没有专门的访问器来提供实现。
- 在这种情况下,编译器生成的类或接口仅包含默认方法,而不会生成专门的访问器类(通常是
-
带兼容性访问器的类或接口:
- 在这种情况下,编译器生成了专门的访问器类(通常是
DefaultImpls
),该类包含接口中默认方法的实现。这个访问器类允许在运行时,即使派生类没有显式实现这些默认方法,仍然可以通过访问器类来调用这些方法,保持二进制兼容性。
- 在这种情况下,编译器生成了专门的访问器类(通常是
在Kotlin中,通过使用 JvmDefaultWithoutCompatibility
或 JvmDefaultWithCompatibility
这两个注解,你可以控制编译器是否生成这种带有兼容性访问器的类或接口。如果选择 JvmDefaultWithoutCompatibility
,则生成的类或接口将不包含专门的兼容性访问器,而 JvmDefaultWithCompatibility
则强制生成带有兼容性访问器的类或接口。
判断是否需要带兼容性访问器的类或接口,取决于你的项目的具体需求和兼容性策略。
不带兼容性访问器的类或接口(使用 JvmDefaultWithoutCompatibility
):
-
新项目: 如果你正在创建一个新的Kotlin项目,并且不依赖于现有的Java或Kotlin代码,可以选择使用不带兼容性访问器的类或接口。这样可以减少生成的字节码大小,并避免引入不必要的访问器类。
-
不需要二进制兼容性: 如果你的库或应用程序不需要与现有Java代码保持二进制兼容性,并且你可以容忍在将来可能对接口进行更改而不保留二进制兼容性的情况下,选择不带兼容性访问器的类或接口。
带兼容性访问器的类或接口(使用 JvmDefaultWithCompatibility
):
-
已有项目并且需要与Java代码交互: 如果你的项目已经存在,并且需要与现有的Java代码进行交互,特别是在Java代码中实现了Kotlin接口的默认方法,那么选择带兼容性访问器的类或接口是一个安全的选择。
-
需要保持二进制兼容性: 如果你的库或应用程序需要与现有Java代码保持二进制兼容性,尤其是在接口可能在将来进行修改时,选择带兼容性访问器的类或接口是更保守的选择。这确保了即使在将来添加了新的默认方法,现有的派生类仍然可以正常工作。
-
涉及公共API: 如果你的接口是一个公共API,可能被其他项目或团队使用,那么选择带兼容性访问器的类或接口通常是一个更安全的选择,以避免破坏现有的实现。
总的来说,选择是否使用带兼容性访问器的类或接口取决于你的项目的特定需求和兼容性要求。如果不确定,可以考虑在项目中试验并评估不同的选项,以了解它们对项目的影响。