Annotation Interface ParametersMustMatchByName
Usually, if your method or constructor has multiple parameters of the same type, it adds risk
of them being passed in the wrong order, particularly if they are primitive types like strings or
ints. You could create a builder, but builders carry significant boilerplate and you could forget
to set a required parameter, resulting in runtime error. By simply annotating the constructor
with @ParametersMustMatchByName, you get compile-time safety for free.
For example if you have a record like the following:
@ParametersMustMatchByName
record Profile(String userId, String userName) {}
You can construct it with
new Profile(currentUser.getId(), currentUser.getName())
But if you change the constructor signature to record Profile(String userName, String
userId), it will fail to compile because the parameter names no longer match the provided
argument expressions, in order.
The currentUser.getId() expression matches the userId parameter name because
the effective tokens of currentUser.getId() are ["current", "user", "id"] ("get"
and "is" prefixes are ignored). It includes as a subsequence the ["user", "id"] tokens
from userId.
Occasionally, if the argument expression is indeed as expected despite not matching the parameter name, you can always add an explicit comment to tell the compiler and the code readers that: "trust me, I know what I'm doing".
For example:
new Dimension(/* width */ list.get(0), /* height */ list.get(1));Or, trailing comments can also be used under the style of one-arg-per-line:
new Dimension(
list.get(0), // width
list.get(1)); // height
In a sense,
/* width */ list.get(0)serves a similar purpose to
.setWidth(list.get(0)) in a builder chain – they both
explicitly spell out "width" as the target to ensure you don't pass in height by mistake.
Except with a @ParametersMustMatchByName-annotated constructor, the per-parameter comment
is on a need basis that's only necessary for code not already self-evident. If you have a
width local variable for example, simply pass it in without the syntax redundancy mandated by
builder.setWidth(width). The most concise code is also the safe code, guaranteed by the
compile-time plugin.
For literal parameters (string literals, int literals, enum constants, class literals), the parameter name matching rule is relaxed if the corresponding method parameter's type is unique (no other parameters share the same type).
Note that method references used as functional interfaces are not checked for parameter name matching between the method declaration and the functional interface's method names.
To use, just ensure you have the following snippet in your pom.xml:
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_core</artifactId>
<version>2.40.0</version>
</path>
<path>
<groupId>com.google.mug</groupId>
<artifactId>mug-errorprone</artifactId>
<version>11.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
- Since:
- 9.9.1