简体   繁体   English

为什么在这种特殊情况下 instanceof 模式匹配不能与 else if 一起使用?

[英]Why doesn't instanceof pattern matching work with else if in this particular case?

The following snippet does not compile on javac, version 17 (Temurin)以下代码段无法在 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
    }
}

It generates this error: cannot find symbol它会生成此错误:找不到符号

cannot find symbol
symbol:   variable s
location: class Instanceof

However, the following (in my opinion) equivalent variations work: With an explicit else block:但是,以下(在我看来)等效变体有效:使用显式 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);
    }
}

Or without an else:或者没有 else:

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

Or with a single if:或使用单个 if:

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

Is this a bug in javac?这是javac中的错误吗? If yes, should I report this, but where exactly?如果是,我应该报告这个,但具体在哪里?

The doesNotWork case is equivalent to this: 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
}

This makes it more obvious that String s is inside a block bounded by curly brackets and is therefore out of scope in the same way that this doesn't work either:这使得String s位于由大括号包围的块内变得更加明显,因此超出了范围,就像这也不起作用一样:

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

In the case where it does work, with the println inside the else, it's equivalent to this:在它确实有效的情况下,在 else 中使用 println,它相当于:

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

Which shows the println being in scope.这表明 println 在范围内。

The relevant bug ticket has been created in the OpenJdk Jira.已在 OpenJdk Jira 中创建了相关的 bug 票证。 It is marked as reproduceable so most probably will be handled as bug, and fixed.它被标记为可复制,因此很可能会被视为错误并已修复。

Here is the aforementioned ticket so we can trace the progress.这是前面提到的票,所以我们可以追踪进度。

Edit : Seems that this issue is going to affect JDK 20 as well.编辑:似乎这个问题也会影响 JDK 20。 Resolution is going to take some time.解决问题需要一些时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM