{"id":19594177,"url":"https://github.com/tlinkowski/basic-annotations","last_synced_at":"2025-04-27T15:33:37.052Z","repository":{"id":57742541,"uuid":"174715733","full_name":"tlinkowski/basic-annotations","owner":"tlinkowski","description":"A couple of basic Java annotations that cover null safety (via JSR 305), collection mutability (via Kotlin), and a few other concepts.","archived":false,"fork":false,"pushed_at":"2019-10-05T04:08:45.000Z","size":197,"stargazers_count":9,"open_issues_count":4,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-05T01:04:40.539Z","etag":null,"topics":["annotation","java","mutability","nullability"],"latest_commit_sha":null,"homepage":"http://annotation.tlinkowski.pl/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tlinkowski.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-03-09T16:06:49.000Z","updated_at":"2022-05-18T13:18:35.000Z","dependencies_parsed_at":"2022-09-09T11:21:14.469Z","dependency_job_id":null,"html_url":"https://github.com/tlinkowski/basic-annotations","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlinkowski%2Fbasic-annotations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlinkowski%2Fbasic-annotations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlinkowski%2Fbasic-annotations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tlinkowski%2Fbasic-annotations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tlinkowski","download_url":"https://codeload.github.com/tlinkowski/basic-annotations/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251162710,"owners_count":21545804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["annotation","java","mutability","nullability"],"created_at":"2024-11-11T08:42:29.575Z","updated_at":"2025-04-27T15:33:32.022Z","avatar_url":"https://github.com/tlinkowski.png","language":"Java","readme":"# Basic Java Annotations\n\n[![Build (Linux)](https://img.shields.io/travis/com/tlinkowski/basic-annotations/master?logo=linux)](https://travis-ci.com/tlinkowski/basic-annotations)\n[![Build (Windows)](https://img.shields.io/appveyor/ci/tlinkowski/basic-annotations/master?logo=windows)](https://ci.appveyor.com/project/tlinkowski/basic-annotations/branch/master)\n[![Code coverage](https://img.shields.io/codecov/c/github/tlinkowski/basic-annotations)](https://codecov.io/gh/tlinkowski/basic-annotations)\n[![Codacy grade](https://img.shields.io/codacy/grade/00dfb34300b94e76b791732690fe8548)](https://app.codacy.com/project/tlinkowski/basic-annotations/dashboard)\n\n[![Maven Central](https://img.shields.io/maven-central/v/pl.tlinkowski.annotation/pl.tlinkowski.annotation.basic?label=Maven%20Central)](https://search.maven.org/search?q=g:pl.tlinkowski.annotation)\n[![Javadocs](https://javadoc.io/badge/pl.tlinkowski.annotation/pl.tlinkowski.annotation.basic.svg?color=blue)](https://javadoc.io/doc/pl.tlinkowski.annotation/pl.tlinkowski.annotation.basic)\n[![Semantic Versioning](https://img.shields.io/badge/-semantic%20versioning-333333)](https://semver.org/)\n[![Automated Release Notes by gren](https://img.shields.io/badge/%F0%9F%A4%96-release%20notes-00B2EE)](https://github-tools.github.io/github-release-notes/)\n\n## Usage\n\n\u003cdetails open\u003e\n\u003csummary\u003eGradle (Kotlin DSL)\u003c/summary\u003e\n\n```kotlin\ncompileOnly(group = \"pl.tlinkowski.annotation\", name = \"pl.tlinkowski.annotation.basic\", version = \"x.y.z\")\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eGradle (Groovy DSL)\u003c/summary\u003e\n\n```groovy\ncompileOnly group: 'pl.tlinkowski.annotation', name: 'pl.tlinkowski.annotation.basic', version: 'x.y.z'\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eMaven\u003c/summary\u003e\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003epl.tlinkowski.annotation\u003c/groupId\u003e\n  \u003cartifactId\u003epl.tlinkowski.annotation.basic\u003c/artifactId\u003e\n  \u003cversion\u003ex.y.z\u003c/version\u003e\n  \u003cscope\u003eprovided\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n\u003c/details\u003e\n\n\u003cdetails open\u003e\n\u003csummary\u003eJPMS (\u003ccode\u003emodule-info.java\u003c/code\u003e)\u003c/summary\u003e\n\n```java\nrequires static pl.tlinkowski.annotation.basic;\n```\n\n\u003c/details\u003e\n\n## Purpose\n\nThe purpose of this library is to provide a couple of basic annotations related to the following concepts:\n\n1.  [Nullability](#nullability)\n\n2.  [Mutability](#mutability) of\n    [`Collection`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Collection.html)s /\n    [`Iterator`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html)s\n\n3.  [Miscellaneous](#miscellaneous)\n\n### Nullability\n\nThe approach to nullability taken by this library is:\n\n\u003e **Everything is non-null by default, unless explicitly annotated as nullable.**\n\nThis approach is directly in line with [Kotlin's approach](https://kotlinlang.org/docs/reference/null-safety.html)\n(although Kotlin enforces it through its type system):\n\n-   `String` (Kotlin) / `String` (Java) → non-null `String`\n-   `String?` (Kotlin) / `@NullOr String` (Java) → `null` or `String`\n\nFor this purpose, the library provides two annotations in the `pl.tlinkowski.annotation.basic` package:\n\n1.  [`@NonNullPackage`](subprojects/pl.tlinkowski.annotation.basic/src/main/java/pl/tlinkowski/annotation/basic/NonNullPackage.java):\n\n    -   [target](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Target.html):\n        [packages](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#PACKAGE)\n\n    -   affects: **all** [type uses](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#TYPE_USE)\n        (e.g. fields, method return types, method parameters, type parameters, local variables) and\n        [type parameters](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#TYPE_PARAMETER)\n        *within the annotated package*\n\n    -   analogous to (except for the scope of affected entities):\n        [`@NonNullApi`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/lang/NonNullApi.html) + \n        [`@NonNullFields`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/lang/NonNullFields.html)\n        in Spring;\n        [`@ParametersAreNonnullByDefault`](https://static.javadoc.io/com.google.code.findbugs/jsr305/3.0.2/javax/annotation/ParametersAreNonnullByDefault.html)\n        in JSR 305\n\n    -   [example usage](subprojects/sample-java-api/src/main/java/pl/tlinkowski/sample/api/annotated/nullability/package-info.java#L21-L24)\n\n2.  [`@NullOr`](subprojects/pl.tlinkowski.annotation.basic/src/main/java/pl/tlinkowski/annotation/basic/NullOr.java):\n\n    -   [target](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Target.html):\n        [type uses](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#TYPE_USE)\n        (e.g. fields, method return types, method parameters, type parameters, local variables) and\n        [type parameters](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#TYPE_PARAMETER)\n\n    -   affects: annotated type use\n\n    -   analogous to (except for the scope of allowed targets):\n        [`@Nullable`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/lang/Nullable.html)\n        in Spring;\n        [`@CheckForNull`](https://static.javadoc.io/com.google.code.findbugs/jsr305/3.0.2/javax/annotation/CheckForNull.html)\n        in JSR-305\n\n    -   [example usage](subprojects/sample-java-api/src/main/java/pl/tlinkowski/sample/api/annotated/nullability/NullabilityAnnotatedSample.java#L33-L41)\n\nThe annotations in this library are based on the dormant Java Specification Request \n[JSR 305](https://jcp.org/en/jsr/detail?id=305). JSR 305 has been chosen for this library after analyzing\n[the following pros \u0026 cons](https://blog.tlinkowski.pl/2019/when-to-use-jsr-305-for-nullability-in-java#assessment-of-jsr-305).\n\nTo sum up, even though I'd rather *not* rely on JSR 305, it seems too well supported right now to discard it.\n\nHowever, should the state of JSR 305 change in favor of dropping its usage, this library will do just that. The purpose\nof this library is to provide `@NonNullPackage` and `@NullOr` annotations that work in the best currently \npossible way.\n\n### Mutability\n\nThe approach to mutability of [`Collection`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Collection.html)s\n(but also [`Iterator`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Iterator.html)s)\ntaken by this library is:\n\n\u003e **Every use of `Collection` or `Iterator` should be annotated with either `@ReadOnly` or `@Mutable`.**\n\nThis approach is in line with [Kotlin's approach](https://kotlinlang.org/docs/reference/collections.html)\n(although Kotlin enforces it through its type system):\n\n-   [`List\u003cT\u003e`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/index.html) (Kotlin)\n    / `@ReadOnly List\u003cT\u003e` (Java) → read-only list of `T`\n\n-   [`MutableList\u003cT\u003e`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-mutable-list/index.html) (Kotlin)\n    / `@Mutable List\u003cT\u003e` (Java) → mutable list of `T`\n\nFor this purpose, this library includes two annotations in the `kotlin.annotations.jvm` package\n(as a transitive dependency on [`kotlin-annotations-jvm`](https://mvnrepository.com/artifact/org.jetbrains.kotlin/kotlin-annotations-jvm)):\n\n1.  [`@ReadOnly`](https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-annotations-jvm/src/kotlin/annotations/jvm/ReadOnly.java):\n\n    -   [target](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Target.html):\n        [fields](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#FIELD),\n        [methods](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#METHOD),\n        [parameters](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#PARAMETER),\n        or [local variables](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#LOCAL_VARIABLE)\n\n    -   affects: annotated type use\n\n    -   [example usage](subprojects/sample-java-api/src/main/java/pl/tlinkowski/sample/api/annotated/mutability/MutabilityAnnotatedSample.java#L30-L33)\n\n2.  [`@Mutable`](https://github.com/JetBrains/kotlin/blob/master/libraries/tools/kotlin-annotations-jvm/src/kotlin/annotations/jvm/Mutable.java):\n \n    -   [target](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Target.html):\n        [fields](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#FIELD),\n        [methods](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#METHOD),\n        [parameters](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#PARAMETER),\n        or [local variables](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#LOCAL_VARIABLE)\n\n    -   affects: annotated type use\n\n    -   [example usage](subprojects/sample-java-api/src/main/java/pl/tlinkowski/sample/api/annotated/mutability/MutabilityAnnotatedSample.java#L35-L38)\n\nThere are three main problems with these annotations, though:\n\n1.  [According to Denis Zharkov](https://youtrack.jetbrains.com/issue/KT-6878#focus=streamItem-27-3198699.0-0),\n    these annotations will probably be renamed once [KT-23812](https://youtrack.jetbrains.com/issue/KT-23812) is done.\n\n2.  These annotations are JDK6-compatible, and hence they cannot target\n    [type uses](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#TYPE_USE)\n    or [type parameters](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/ElementType.html#TYPE_PARAMETER)\n    (introduced in JDK 8). There's an issue about improving this ([KT-28982](https://youtrack.jetbrains.com/issue/KT-28982)),\n    but it seems idle now.\n\n3.  These annotations are not retained at runtime (`@Retention(RetentionPolicy.CLASS)`), which could be useful\n    (at least theoretically).\n\nTo sum up, the main reason this library does not introduce its own annotations is that Kotlin wouldn't recognize them,\nand they are very useful for Kotlin interop. However, once [KT-23812](https://youtrack.jetbrains.com/issue/KT-23812)\nis done, this library will probably migrate to some\n[new annotations](https://github.com/Kotlin/KEEP/blob/jvm-meta-annotations-artifact/proposals/jvm-meta-annotations-artifact.md)\nthat can be understood by Kotlin.\n\n### Miscellaneous\n\n-   [`@VisibleForTesting`](subprojects/pl.tlinkowski.annotation.basic/src/main/java/pl/tlinkowski/annotation/basic/VisibleForTesting.java):\n    Corresponds to Guava's\n    [`@VisibleForTesting`](https://google.github.io/guava/releases/28.0-jre/api/docs/com/google/common/annotations/VisibleForTesting.html)\n    annotation.\n\n## Sample Projects\n\nSample projects for this library can be found in [`sample`](subprojects/sample) subdirectory:\n\n-   [`pl.tlinkowski.annotation.sample.api`](subprojects/sample/pl.tlinkowski.annotation.sample.api):\n    sample Java API annotated with `@NonNullPackage` and `@ReadOnly`\n\n-   [`pl.tlinkowski.annotation.sample.usage.java`](subprojects/sample/pl.tlinkowski.annotation.sample.usage.java):\n    usage of the above API (both correct and incorrect, the latter resulting in warnings from IntelliJ IDEA)\n\n-   [`pl.tlinkowski.annotation.sample.usage.kotlin`](subprojects/sample/pl.tlinkowski.annotation.sample.usage.kotlin):\n    usage of the above API (both correct and incorrect, the latter resulting in errors from Kotlin compiler)\n\n## Requirements\n\nUsage: JDK 8+.\n\nBuilding: Gradle 5+, JDK 11+.\n\n## About the Author\n\nSee my webpage ([tlinkowski.pl](https://tlinkowski.pl/)) or\nfind me on Twitter ([@t_linkowski](https://twitter.com/t_linkowski)).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftlinkowski%2Fbasic-annotations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftlinkowski%2Fbasic-annotations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftlinkowski%2Fbasic-annotations/lists"}