Class 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 to true 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 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
    Since:
    8.37
    • Nested Class Summary

      • Nested classes/interfaces inherited from class com.puppycrawl.tools.checkstyle.api.AutomaticBean

        com.puppycrawl.tools.checkstyle.api.AutomaticBean.OutputStreamOptions
    • 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.
    • 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
      • Methods inherited from class com.puppycrawl.tools.checkstyle.api.AutomaticBean

        configure, contextualize, getConfiguration, setupChild
    • 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
    • Constructor Detail

      • PreferMethodReferenceCheck

        public PreferMethodReferenceCheck()
    • 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 class com.puppycrawl.tools.checkstyle.api.AbstractCheck
      • getAcceptableTokens

        public int[] getAcceptableTokens()
        Specified by:
        getAcceptableTokens in class com.puppycrawl.tools.checkstyle.api.AbstractCheck
      • getRequiredTokens

        public int[] getRequiredTokens()
        Specified by:
        getRequiredTokens in class com.puppycrawl.tools.checkstyle.api.AbstractCheck
      • visitToken

        public void visitToken​(com.puppycrawl.tools.checkstyle.api.DetailAST ast)
        Overrides:
        visitToken in class com.puppycrawl.tools.checkstyle.api.AbstractCheck