You can't declare the same variable in two different places using pattern matching. Those are still two different variables, with two different scopes.
Perhaps, we can clear the confusion by giving them different names:
if (!(x instanceof Comment comment)) {
if (!(x instanceof Document doc && doc.getFirstChild() instanceof Comment comment2)) {
return null;
}
//comment2 and doc are in scope here,
//but their scope ends with an enclosing block
System.out.println(comment2.toString());
}
//FAIL! You can't access comment2 outside its scope
System.out.println(comment2.toString());
//FAIL! You can't access comment here because
//the compiler can't guarantee that the block above exited.
System.out.prinltn(comment.toString()
You can verify that pattern-matched variables still remain in their enclosing scope using a simple example like this:
{
Object o = null;
if(!(o instanceof String s)) {
return;
}
System.out.println(s); //OK
}
System.out.println(s); //Doesn't work
Sorry, I don't really have an elegant alternative for you to use. You can achieve what you want with a somewhat ugly workaround:
Comment comment;
if (!(x instanceof Comment c)) {
if (!(x instanceof Document doc && doc.getFirstChild() instanceof Comment c)) {
return null;
}
comment = c;
} else {
comment = c;
}
System.out.println(comment.toString());
This workaround gets better if you can move this snippet into a separate method:
private static Comment extractComment(Node x) {
if (!(x instanceof Comment comment)) {
if (!(x instanceof Document doc && doc.getFirstChild() instanceof Comment comment)) {
return null;
}
return comment;
}
return comment;
}
Or even:
private static Comment extractComment(Node x) {
if (x instanceof Comment comment) {
return comment;
}
if (x instanceof Document doc && doc.getFirstChild() instanceof Comment comment) {
return comment;
}
return null;
}