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() is ["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>9.9.2</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
- Since:
- 9.9.1