rspec/rules/S2109/java/rule.adoc

66 lines
2.6 KiB
Plaintext
Raw Normal View History

== Why is this an issue?
Denoted by the "@" symbol, annotations are metadata that can be added to classes, methods, and variables for various
purposes such as documentation, code analysis, and runtime processing.
2021-04-28 16:49:39 +02:00
Annotations have retention policies that determine in which context they are retained and available for use.
There are three retention policies for annotations:
2021-04-28 16:49:39 +02:00
* `RetentionPolicy.SOURCE` - Annotations are only available during compilation and code analysis.
They are not included in the compiled class file and are not available at runtime.
E.G. `@Override`, `@SuppressWarnings`
* `RetentionPolicy.CLASS` - Annotations are included in the compiled class file providing information to the compiler,
but they are not retained by the JVM at runtime. This is the default retention policy. E.G. `@PreviewFeature`
* `RetentionPolicy.RUNTIME` - Annotations are included in the compiled class file and available at runtime.
They can be accessed and used by the program through reflection.
E.G. `@FunctionalInterface`, `@Deprecated`
2021-04-28 16:49:39 +02:00
It is important to understand that only annotations having the `RUNTIME` retention policy can be accessed at runtime
using reflection. For example, the following if condition is true when the method argument is the
`java.util.function.Function` class:
2021-04-28 16:49:39 +02:00
[source,java]
----
void execute(Class<?> cls) {
if (cls.isAnnotationPresent(FunctionalInterface.class)) {
// ...
}
}
----
Therefore, it is an issue to use reflection in combination with annotations with the `SOURCE` or `CLASS` retention policy because they
are not present at runtime. For example, in the JVM source code, the `hashCode()` method of the `Integer` class has
the `@Override` annotation. However, the following if condition will always be false even if the method argument is the
`Integer#hashCode()` method because `@Override` has the `SOURCE` retention policy:
2021-04-28 16:49:39 +02:00
2022-02-04 17:28:24 +01:00
[source,java]
2021-04-28 16:49:39 +02:00
----
void execute(Method method) {
if (method.isAnnotationPresent(Override.class)) { // Noncompliant, if condition will always be false because
// @Override is declared with @Retention(RetentionPolicy.SOURCE)
// ...
}
}
2021-04-28 16:49:39 +02:00
----
This rule detects improper reflective access on annotations having the `SOURCE` or `CLASS` retention policy.
== Resources
=== Documentation
* https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/annotation/RetentionPolicy.html[Oracle SDK - java.lang.annotation.RetentionPolicy]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
"@xxx" is not available at runtime and cannot be seen with reflection.
endif::env-github,rspecator-view[]