Fwd: JEP 305: Forcing a pattern match

Daniel Trebbien dtrebbien at gmail.com
Sat Nov 11 14:52:06 UTC 2017


Working on a particular file
<https://github.com/apache/incubator-netbeans/blob/951ac9aad3686f2af019e5d73015c867b37025df/java.hints/src/org/netbeans/modules/java/hints/introduce/Flow.java#L1389..L1407>
in Apache NetBeans' source repository, I came across the following code:

for (Tree member : node.getMembers()) {
    if (member.getKind() == Kind.BLOCK) {
        if (((BlockTree) member).isStatic()) {
            staticInitializers.add(member);
        } else {
            instanceInitializers.add(member);
        }
    } else if (member.getKind() == Kind.VARIABLE && ((VariableTree)
member).getInitializer() != null) {
        if (((VariableTree) member).getModifiers().
getFlags().contains(Modifier.STATIC)) {
            staticInitializers.add((VariableTree) member);
        } else {
            instanceInitializers.add((VariableTree) member);
        }
    } else if (isConstructor(new TreePath(getCurrentPath(), member))) {
        constructors.add((MethodTree) member);
    } else {
        others.add(member);
    }
}

With respect to the first else if, notice that there are four casts of
member to VariableTree.  It turns out that the last two casts are not
necessary, but let's pretend that they are for a moment.

I think that it would be useful to be able to define a new variable to hold
the result of casting member to VariableTree, whose scope is restricted to
the else if.

With JEP 305 <http://openjdk.java.net/jeps/305>, this can be accomplished
via a matches expression, as in:

for (Tree member : node.getMembers()) {
    if (member.getKind() == Kind.BLOCK) {
        if (((BlockTree) member).isStatic()) {
            staticInitializers.add(member);
        } else {
            instanceInitializers.add(member);
        }
    } else if (member.getKind() == Kind.VARIABLE && member matches
VariableTree varMember && varMember.getInitializer() != null) {
        if (varMember.getModifiers().getFlags().contains(Modifier.STATIC)) {
            staticInitializers.add(varMember);
        } else {
            instanceInitializers.add(varMember);
        }
    } else if (isConstructor(new TreePath(getCurrentPath(), member))) {
        constructors.add((MethodTree) member);
    } else {
        others.add(member);
    }
}

However, the matches operator would perform an unnecessary instanceof
check; here, we know that member is an instance of VariableTree.

Perhaps another operator should be added, say asmatch, which would attempt
to force the pattern match, without performing additional checks.  In the
case of a type test pattern, this would declare a variable set to a type
cast.

One quirk of such an operator is that it would always result in true.  Any
cases where the expression does not match the pattern would result in some
runtime exception such as ClassCastException.


More information about the amber-spec-comments mailing list