有没有办法检查 Lambda 变量的显式类型?

Is there a way to check for explicit types on Lambda variables?

接受这个 Lambda:

final List<String> badKeys = pivMap.entrySet().stream()
 .filter(entry -> StringUtils.trimToNull(entry.getValue()) == null || entry.getValue().equals("{}") || entry.getValue().equals("{ }"))
 .map(Map.Entry::getKey)
 .collect(Collectors.toList());

我们要确保 Lambda 变量有明确的类型:

final List<String> badKeys = pivMap.entrySet().stream()
 .filter((final Map.Entry<String, String> entry) -> StringUtils.trimToNull(entry.getValue()) == null || entry.getValue().equals("{}") || entry.getValue().equals("{ }"))
 .map(Map.Entry::getKey)
 .collect(Collectors.toList());

有没有办法使用 puppycrawl checkstyle 来检查上面的 lambda 表达式中是否存在类型?在这种情况下,变量的类型声明是:(final Map.Entry<String, String> entry)

这可以通过 MatchXPathCheck 实现:

配置:


<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
        "http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">

<module name="Checker">
    <property name="charset" value="UTF-8"/>
    <property name="haltOnException" value="true"/>
    <property name="severity" value="error"/>

    <module name="TreeWalker">
        <module name="MatchXpath">
            <property name="query" value="//LAMBDA[IDENT][1]"/>
            <message key="matchxpath.match"
                     value="Lambda parameters must have type."/>
        </module>
    </module>
</module>

这里我们使用 XPath 表达式来检查 IDENT 是否是 lambda 的第一个子代,这意味着在这种情况下它不是类型化的。

Java 示例:


import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;

public class MyClass {

    void badLambda(Map<String, String> pivMap) {
        final List<String> badKeys = pivMap.entrySet().stream()
                .filter(entry -> StringUtils.trimToNull(entry.getValue()) == null // violation
                        || entry.getValue().equals("{}")
                        || entry.getValue().equals("{ }"))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }

    void goodLambda(Map<String, String> pivMap) {
        final List<String> badKeys = pivMap.entrySet().stream()
                .filter((final Map.Entry<String, String> entry) -> StringUtils.trimToNull(entry.getValue()) == null // ok
                        || entry.getValue().equals("{}")
                        || entry.getValue().equals("{ }"))
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
    }
}

结果:


➜  src java -jar checkstyle-8.41-all.jar -c config.xml MyClass.java
Starting audit...
[ERROR] MyClass.java:11:31: Lambda parameters must have type. [MatchXpath]
Audit done.
Checkstyle ends with 1 errors.