Class PreferMethodReferenceCheck
- java.lang.Object
-
- com.puppycrawl.tools.checkstyle.api.AutomaticBean
-
- com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter
-
- com.puppycrawl.tools.checkstyle.api.AbstractCheck
-
- com.github.sevntu.checkstyle.checks.coding.PreferMethodReferenceCheck
-
- All Implemented Interfaces:
com.puppycrawl.tools.checkstyle.api.Configurable,com.puppycrawl.tools.checkstyle.api.Contextualizable
public class PreferMethodReferenceCheck extends com.puppycrawl.tools.checkstyle.api.AbstractCheckChecks 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
detectForExpressionshould be set totrueto enable detection for expressions. See link for more info.-
Property
detectForExpression- Enable detection for cases when method in lambda is invoked on expression. Type isboolean. Default value isfalse.
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 castParent is
com.puppycrawl.tools.checkstyle.TreeWalkerViolation Message Keys:
-
method.reference
- Since:
- 8.37
-
-
Field Summary
Fields Modifier and Type Field Description static StringMSG_METHOD_REFA key is pointing to the warning message text in "messages.properties" file.
-
Constructor Summary
Constructors Constructor Description PreferMethodReferenceCheck()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description int[]getAcceptableTokens()int[]getDefaultTokens()int[]getRequiredTokens()voidsetDetectForExpression(boolean detectForExpression)Setter to enable detection for cases when method in lambda is invoked on expression.voidvisitToken(com.puppycrawl.tools.checkstyle.api.DetailAST ast)-
Methods inherited from class com.puppycrawl.tools.checkstyle.api.AbstractCheck
beginTree, clearViolations, destroy, finishTree, getFileContents, getFilePath, getLine, getLineCodePoints, getLines, getTabWidth, getTokenNames, getViolations, init, isCommentNodesRequired, leaveToken, log, log, log, setFileContents, setTabWidth, setTokens
-
Methods inherited from class com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter
finishLocalSetup, getCustomMessages, getId, getMessageBundle, getSeverity, getSeverityLevel, setId, setSeverity
-
-
-
-
Field Detail
-
MSG_METHOD_REF
public static final String MSG_METHOD_REF
A key is pointing to the warning message text in "messages.properties" file.- See Also:
- Constant Field Values
-
-
Method Detail
-
setDetectForExpression
public void setDetectForExpression(boolean detectForExpression)
Setter to enable detection for cases when method in lambda is invoked on expression.- Parameters:
detectForExpression- enable detection for cases when method in lambda is invoked on expression
-
getDefaultTokens
public int[] getDefaultTokens()
- Specified by:
getDefaultTokensin classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
getAcceptableTokens
public int[] getAcceptableTokens()
- Specified by:
getAcceptableTokensin classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
getRequiredTokens
public int[] getRequiredTokens()
- Specified by:
getRequiredTokensin classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
visitToken
public void visitToken(com.puppycrawl.tools.checkstyle.api.DetailAST ast)
- Overrides:
visitTokenin classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
-