Gradle (Kotlin DSL)
compileOnly(group = "pl.tlinkowski.annotation", name = "pl.tlinkowski.annotation.basic", version = "x.y.z")Gradle (Groovy DSL)
compileOnly group: 'pl.tlinkowski.annotation', name: 'pl.tlinkowski.annotation.basic', version: 'x.y.z'Maven
<dependency>
<groupId>pl.tlinkowski.annotation</groupId>
<artifactId>pl.tlinkowski.annotation.basic</artifactId>
<version>x.y.z</version>
<scope>provided</scope>
</dependency>JPMS (module-info.java)
requires static pl.tlinkowski.annotation.basic;The purpose of this library is to provide a couple of basic annotations related to the following concepts:
The approach to nullability taken by this library is:
Everything is non-null by default, unless explicitly annotated as nullable.
This approach is directly in line with Kotlin's approach (although Kotlin enforces it through its type system):
String(Kotlin) /String(Java) → non-nullStringString?(Kotlin) /@NullOr String(Java) →nullorString
For this purpose, the library provides two annotations in the pl.tlinkowski.annotation.basic package:
-
-
affects: all type uses (e.g. fields, method return types, method parameters, type parameters, local variables) and type parameters within the annotated package
-
analogous to (except for the scope of affected entities):
@NonNullApi+@NonNullFieldsin Spring;@ParametersAreNonnullByDefaultin JSR 305
-
-
target: type uses (e.g. fields, method return types, method parameters, type parameters, local variables) and type parameters
-
affects: annotated type use
-
analogous to (except for the scope of allowed targets):
@Nullablein Spring;@CheckForNullin JSR-305
-
The annotations in this library are based on the dormant Java Specification Request JSR 305. JSR 305 has been chosen for this library after analyzing the following pros & cons.
To sum up, even though I'd rather not rely on JSR 305, it seems too well supported right now to discard it.
However, should the state of JSR 305 change in favor of dropping its usage, this library will do just that. The purpose
of this library is to provide @NonNullPackage and @NullOr annotations that work in the best currently
possible way.
The approach to mutability of Collections
(but also Iterators)
taken by this library is:
Every use of
CollectionorIteratorshould be annotated with either@ReadOnlyor@Mutable.
This approach is in line with Kotlin's approach (although Kotlin enforces it through its type system):
-
List<T>(Kotlin) /@ReadOnly List<T>(Java) → read-only list ofT -
MutableList<T>(Kotlin) /@Mutable List<T>(Java) → mutable list ofT
For this purpose, this library includes two annotations in the kotlin.annotations.jvm package
(as a transitive dependency on kotlin-annotations-jvm):
-
-
target: fields, methods, parameters, or local variables
-
affects: annotated type use
-
-
-
target: fields, methods, parameters, or local variables
-
affects: annotated type use
-
There are three main problems with these annotations, though:
-
According to Denis Zharkov, these annotations will probably be renamed once KT-23812 is done.
-
These annotations are JDK6-compatible, and hence they cannot target type uses or type parameters (introduced in JDK 8). There's an issue about improving this (KT-28982), but it seems idle now.
-
These annotations are not retained at runtime (
@Retention(RetentionPolicy.CLASS)), which could be useful (at least theoretically).
To sum up, the main reason this library does not introduce its own annotations is that Kotlin wouldn't recognize them, and they are very useful for Kotlin interop. However, once KT-23812 is done, this library will probably migrate to some new annotations that can be understood by Kotlin.
@VisibleForTesting: Corresponds to Guava's@VisibleForTestingannotation.
Sample projects for this library can be found in sample subdirectory:
-
pl.tlinkowski.annotation.sample.api: sample Java API annotated with@NonNullPackageand@ReadOnly -
pl.tlinkowski.annotation.sample.usage.java: usage of the above API (both correct and incorrect, the latter resulting in warnings from IntelliJ IDEA) -
pl.tlinkowski.annotation.sample.usage.kotlin: usage of the above API (both correct and incorrect, the latter resulting in errors from Kotlin compiler)
Usage: JDK 8+.
Building: Gradle 5+, JDK 11+.
See my webpage (tlinkowski.pl) or find me on Twitter (@t_linkowski).