kotlin 注释
最近,我与一位同事进行了一次有趣的对话,内容涉及在Java / Kotlin代码中使用注释。 他曾在不鼓励使用某些语言功能(在这种情况下为通过注释进行元编程)的组织中工作,因为它们“太神奇了”并且“难以理解”。 虽然选择避免使用框架或语言的某些功能是合理的,因为它们通常被认为是有害的,但一个开发人员的“魔力”是另一位开发人员的日常生产力工具。
我将以另一种方式重申对“魔术”的反对:
我不了解该语言的这一功能,因此我选择不使用它,而无需考虑其预期的用法或可能带来的生产率提高。
作为开发人员,了解何时以及如何使用我们可以使用的工具来解决我们使用软件解决的问题是我们的工作。 因此,保持开放的态度来利用我们使用的语言和框架的功能可以极大地提高生产力。 本文介绍了Kotlin和Java中注释的一些应用程序,并提出了一些对所看到的注释进行分类的方法,以便您可以推断出它们的预期用途。
什么是注释?
在较高的层次上,注释为编译器提供了有关其正在编译的代码的信息,以便程序员可以更改其行为(这就是我们使用术语“元编程”的原因)或在运行时提供有关正在运行的代码的其他信息。 与批注处理器(在编译时运行)结合使用时,某些批注可用于生成编译错误或警告,甚至生成更多代码供编译器进行编译。
因此,注释的属性只能是其他注释或值(基元,字符串,基元/字符串数组,类)。
注释提供什么通用利益?
使用注释,您可以编写更简洁明了的代码,并且不太容易出错。 它们还可以通过向开发人员指示应如何使用代码来增强代码的可读性。
注释如何使用?
据我所知,它们的用法可以分为以下三类(我使用自己的术语):
- 标记(BINARY / CLASS)
- 浓缩机(运行时)
- 发电机(来源)
标记物
标记不是很性感,但是它们仍然很重要。 它们既可以向读者(代码)告知已注释的语言元素的性质(如类,类型,字段/属性等),也可以向静态分析工具或编译器告知被注释的元素。 它们始终包含在类文件中(这就是AnnotationRetention.BINARY
/ RetentionPolicy.CLASS
枚举的含义),以便它们的用法与通过代码创建的任何jar文件一起发布。
Java中的@Deprecated
是一个标记,旨在告知开发人员此Element即将消失,并且编写任何消耗该Element的新代码可能会在将来为您增加更多工作,因为您将被迫迁移(通常是在主要版本更新时)。 某些IDE使用此批注向用户表明已弃用该元素。 Kotlin中的@Deprecated
已得到增强,以允许开发人员提供@ReplaceWith
成员,该成员将允许某些IDE(IntelliJ / Android Studio)用非弃用的代码智能地替换弃用的代码。 但大多数情况下,这是供代码阅读者使用的工具。
Java中的另一个有用的标记注释(即使它具有RetentionPolicy.RUNTIME)是@Nonnull
(这是JSR-305的结果的一部分)。 如果你使用谷歌的执行,这个注释发生在的Java /Kotlin互操作是有益的,因为你的Kotlin代码就能告诉@Nonnull String foo
是String
在Kotlin而不是String?
。 这也有助于进行静态分析工具(例如findbugs),从而可以跳过空检查。 如果您想知道,此批注在@Nullable
有一个伴随@Nullable
。
浓缩机
扩充程序将信息添加到运行时可读的语言Element中(因此,这些批注具有AnnotationRetention.RUNTIME
/ RetentionPolicy.RUNTIME
)。 举例来说,假设您正在开发自定义XML序列化/反序列化库,以避免您的用户需要编写自定义序列化器/反序列化器类。 然后,您可以使用一小组注释与单个序列化器/反序列化器结合使用,该序列化器/解序列器读取要在其中进行序列化的类的元素上的注释中包含的信息。 有一个执行此操作的库: http : //simple.sourceforge.net/ 。
我个人最喜欢的利用运行时注释的库是(Retrofit2)[ https://square.github.io/retrofit/ ]。 Retrofit2使用反射来生成Java代理对象,这些对象仅能够基于您的方法声明来执行网络调用。 例如,
public interface UserService {
@POST("users/new")
Call<User> createUser(@Body User user);
}
进行调用时,将在运行时读取@POST
和@Body
批注,并在执行此调用时,改造将在@POST
批注中组装一个与端点相对应的URL,并创建具有以下序列化形式的OkHttp请求:请求主体中的User
对象。 (如果您不知道如何配置改造来执行此操作,建议阅读文档)。
太好了吧? 特别是在Android上, AnnotationRetention.RUNTIME
/ RetentionPolicy.RUNTIME
批注具有成本: https : //blog.nimbledroid.com/2016/02/23/slow-Android-reflection.html 。 因此,在疯狂使用它们进行所有操作之前-至少在Android项目中,请注意其中涉及的成本。
发电机
Kotlin和Java都具有注释处理功能。 注释处理器在项目编译时运行(因此,它们本身可以通过AnnotationRetention.SOURCE
/ RetentionPolicy.SOURCE
看到注释。) 他们可以做的事情很简单,例如添加注释以将输出记录到控制台,或者复杂的事情,例如生成要编译的代码。 生成器特别适用于传统的重用模式崩溃的情况,并且对于消除样板代码很有用。
例如,如果您曾经实现过构建器模式,以使具有许多字段的类的实例更易于理解和更多地自我说明,则您可能熟悉与之关联的样板。 您会发现自己经常经历复制-粘贴-更改流程。 重复执行10或20次此流程后,您可能在某个地方犯了一个错误。 然后,为了编写合理的equals
, hashCode
和toString
方法,您将不得不重复该流程三遍。 您还必须编写一个构造器,该构造器了解如何应用该构造器构造对象,而不会意外将错误的构造器字段分配给错误的类字段。
输入Google出色的AutoValue注释处理器: https : //github.com/google/auto/blob/master/value/userguide/builders.md 。 使用此工具,您可以声明类的抽象版本和该类的构建器的抽象版本,从而将实现细节委托给注释处理器。 此外,还将生成equals
, hashCode
和toString
,方法以及该类的构造函数。
假设您现在必须向该类添加一个字段。 不必担心使构造函数, equals,
hashCode , and
toString`方法的实现保持最新,而只需为类及其生成器声明一个抽象方法。 下次编译代码时,实际的实现将被更新。
但这还不是全部。 AutoValue被设计为可扩展扩展,并且引入了许多AutoValue扩展以提高您的生产率。
序列化是AutoValue的自然扩展,很多扩展会生成由AutoValue生成的类的对象的序列化器/反序列化器。 我将在本文中突出显示auto-value-moshi作为代表性库,因为还有一个名为moshi-codegen的附加Kotlin注释处理器,该处理器将在Kotlin类上运行并生成将Kotlin对象与JSON序列化/反序列化的Kotlin类。
结论
了解如何应用可供使用的工具以解决软件开发人员所面临的问题非常重要。 与其避免避免使用某些“魔术”工具,还应学习一些知识以使其神秘化。
注释是一个有用的工具,可以提高您在Kotlin / Java中的生产率,并在适当使用时提高代码质量。 因此,下次您看到一些带有@
Java / Kotlin时,我希望您能够更多地理解
翻译自: https://dev.to/ryansgot/kotlin-java-annotations-they-re-where-it-s-anl
kotlin 注释