The following snippet does not compile on javac, version 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:
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:
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:
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? If yes, should I report this, but where exactly?
The doesNotWork
case is equivalent to this:
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:
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:
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.