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 it will fail to compile if the constructor were defined as
record Profile(String userName, String userId). 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),
which includes as a subsequence the ["user", "id"] tokens from userId.
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.1</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
- Since:
- 9.9.1