public class PreferMethodReferenceCheck
extends com.puppycrawl.tools.checkstyle.api.AbstractCheck
Checks that lambda usage can be replaced with method reference.
Rationale: method/constructor references are commonly agreed to be, most of the time,
more compact and readable than using lambdas, and are therefore preferred.
Method/constructor references omit information like parameter names and can be not very readable
if left side is a long expression, but it is mostly exception cases.
Some lambdas are not semantically equal to method references, e.g. if method invocation
is performed on some expression. This happens because lambda has lazy evaluation,
while when using method reference, target expression is evaluated early, which can
bring some unexpected side effects.
Such cases with expressions are not detected by default configuration,
additional property detectForExpression should be set to true to enable
detection for expressions.
See link
for more info.
detectForExpression -
Enable detection for cases when method in lambda is invoked on expression.
Type is boolean.
Default value is false.
To configure the check:
<module name="PreferMethodReference"/>
Example:
class Test {
BiConsumer<Long, Long> c = (a, b) -> sum(a,b); // violation
BiConsumer<Long, Long> c1 = Long::sum; // corrected version
BiFunction<Object, Object, Boolean> d = (a, b) -> a.equals(b); // violation
BiFunction<Object, Object, Boolean> d1 = Object::equals; // corrected version
Consumer<Object> e = arg -> this.voidMethod(arg); // violation
Consumer<Object> e1 = this::voidMethod; // corrected version
Consumer<MyClass> f = arg -> arg.voidMethod(); // violation
Consumer<MyClass> f1 = MyClass::voidMethod; // corrected version
Function<String, String> g = arg -> "myLiteral".concat(arg); // violation
Function<String, String> g1 = "myLiteral"::concat; // corrected version
Supplier<Object> s = () -> new Object(); // violation
Supplier<Object> s1 = Object::new; // corrected version
Function<Integer, Object> t = arg -> new int[arg]; // violation
Function<Integer, Object> t1 = int[]::new; // corrected version
Function<Long, Long> exp = arg -> {return a.longValue();}; // violation
Function<Long, Long> exp1 = Long::longValue; // corrected version
Runnable r = () -> System.out.println(); // OK because System.out is an expression
}
To configure the check to detect violations on expressions:
<module name="PreferMethodReference"> <property name="detectForExpression" value="true"/> </module>
Example:
class Test {
String field;
Consumer<Object> c = a -> System.out.println(a); // violation
Consumer<Object> c = System.out::println; // corrected version
Function<String, String< func =
bool -> (bool() ? null : field).concat(bool); // violation
Function<String, String< func1 =
(bool() ? null : field)::concat; // corrected version
}
Note: This check is not type-aware, so some cases cannot be reported as violation, e.g.
Function<String, Object> f1 =
a -> (Object) "string".concat(a); // no violation because of cast
Parent is com.puppycrawl.tools.checkstyle.TreeWalker
Violation Message Keys:
method.reference
| Modifier and Type | Field and Description |
|---|---|
static String |
MSG_METHOD_REF
A key is pointing to the warning message text in "messages.properties"
file.
|
| Constructor and Description |
|---|
PreferMethodReferenceCheck() |
| Modifier and Type | Method and Description |
|---|---|
int[] |
getAcceptableTokens() |
int[] |
getDefaultTokens() |
int[] |
getRequiredTokens() |
void |
setDetectForExpression(boolean detectForExpression)
Setter to enable detection for cases when method in lambda is invoked on expression.
|
void |
visitToken(com.puppycrawl.tools.checkstyle.api.DetailAST ast) |
beginTree, clearMessages, destroy, finishTree, getFileContents, getLine, getLines, getMessages, getTabWidth, getTokenNames, init, isCommentNodesRequired, leaveToken, log, log, log, setFileContents, setTabWidth, setTokensfinishLocalSetup, getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, setId, setSeveritypublic static final String MSG_METHOD_REF
public void setDetectForExpression(boolean detectForExpression)
detectForExpression - enable detection for cases
when method in lambda is invoked on expressionpublic int[] getDefaultTokens()
getDefaultTokens in class com.puppycrawl.tools.checkstyle.api.AbstractCheckpublic int[] getAcceptableTokens()
getAcceptableTokens in class com.puppycrawl.tools.checkstyle.api.AbstractCheckpublic int[] getRequiredTokens()
getRequiredTokens in class com.puppycrawl.tools.checkstyle.api.AbstractCheckpublic void visitToken(com.puppycrawl.tools.checkstyle.api.DetailAST ast)
visitToken in class com.puppycrawl.tools.checkstyle.api.AbstractCheckCopyright © 2021. All rights reserved.