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.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 totrue
to 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 cast
Parent is
com.puppycrawl.tools.checkstyle.TreeWalker
Violation Message Keys:
-
method.reference
- Since:
- 8.37
-
-
Field Summary
Fields Modifier and Type Field Description static String
MSG_METHOD_REF
A 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()
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)
-
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:
getDefaultTokens
in classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
getAcceptableTokens
public int[] getAcceptableTokens()
- Specified by:
getAcceptableTokens
in classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
getRequiredTokens
public int[] getRequiredTokens()
- Specified by:
getRequiredTokens
in classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
visitToken
public void visitToken(com.puppycrawl.tools.checkstyle.api.DetailAST ast)
- Overrides:
visitToken
in classcom.puppycrawl.tools.checkstyle.api.AbstractCheck
-
-