如果在此特定情况下,为什么模式匹配实例不能与其他模式匹配一起使用?

2022-09-01 16:05:53

以下代码片段无法在 javac 版本 17 (Temurin) 上编译

class Instanceof {
    static void doesNotWork(Object o) {
        if (o == null) {
            throw new Error();
        } else if (!(o instanceof String s)) {
            throw new Error();
        }   
        System.out.println(s); // error here
    }
}

它生成此错误: 找不到符号

cannot find symbol
symbol:   variable s
location: class Instanceof

但是,以下(在我看来)等效变体有效:使用显式 else 块:

static void doesWork(Object o) {
    if (o == null) {
        throw new Error();
    } else if (!(o instanceof String s)) {
        throw new Error();
    } else {
        System.out.println(s);
    }
}

或者没有别的:

static void doesWork(Object o) {
    if (o == null) {
        throw new Error();
    }
    if (!(o instanceof String s)) {
        throw new Error();
    }
    System.out.println(s);
}

或者使用单个,如果:

static void doesWork(Object o) {
    if (o == null || !(o instanceof String s)) {
        throw new Error();
    }
    System.out.println(s);
}

这是javac中的一个错误吗?如果是,我应该报告此事,但究竟在哪里?


答案 1

该案例等效于此:doesNotWork

static void doesNotWork(Object o) {
    if (o == null) {
        throw new Error();
    } else {
        if (!(o instanceof String s)) {
            throw new Error();
        }
    }
    System.out.println(s); // error here
}

这使得它更明显地位于由大括号限定的块内,因此超出了范围,就像这也不起作用一样:String s

static void doesNotWork(Object o) {
    {
        if (!(o instanceof String s)) {
            throw new Error();
        }
    }
    System.out.println(s); // error here
}

在它确实有效的情况下,使用println在other中,它等效于这个:

if (o == null) {
    throw new Error();
} else {
    if (!(o instanceof String s)) {
        throw new Error();
    } else {
        System.out.println(s);
    }
}

这显示了 println 在范围内。


答案 2

相关的 bug 票证已在 OpenJdk Jira 中创建。它被标记为可重现,因此很可能会作为错误处理并修复。

这是上述票证,因此我们可以跟踪进度。

编辑:似乎这个问题也会影响JDK 20。解决将需要一些时间。


推荐