Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Pattern Variable Scope

I am going through Oracle's official docs to understand Pattern Variable scope in Java 17. In the following example, the method testScope1 works as explained in the docs, but the method testScope2 gives a compilation error. I am not able to figure out why void return type of the method is causing the issue?

interface Vehicle{}
class Car implements Vehicle{}

class Pattern{
    public int testScope1(Vehicle v){
        if(!(v instanceof Car c)){
            return 1;
        }
        System.out.println(c.toString());  //WORKS FINE
        return 2; 
    }
    public void testScope2(Vehicle v){
        if(!(v instanceof Car c)){
                 
        }
        System.out.println(c.toString());  //COMPILE TIME ERROR: Cannot resolve symbol c
    }
}
like image 948
Steve Avatar asked Mar 23 '26 04:03

Steve


1 Answers

Pattern variables (binding variables declared in patterns) use flow-sensitive scoping. Unlike ordinary locals, which are in scope for in contiguous regions, pattern variables are in scope where they would be definitely assigned by their declaring pattern.

If you have an if statement:

if (x instanceof Foo(var v)) { 
    A;
}
else {
    B;
}

then v is in scope for A, but not for B, because we are not guaranteed that v would be definitely assigned a value in the cases where we reach B. If we invert our test using the obvious refactoring:

if (!(x instanceof Foo(var v))) { 
    B;
}
else {
    A;
}

the same is true; v is in scope at A but not B. The rules are exactly the same as the definite assignment rules for locals -- "is this value guaranteed to have been assigned a value if I reach this point."

Other conditional constructs, such as short-circuiting && and ||, also participate in this scoping. For example, the following is valid:

if (x instanceof Foo(var v) && v != null) { 
    A;
}

but the following is not:

if (x instanceof Foo(var v) || v != null) { 
    A;
}

because in the latter, v is not guaranteed to have been assigned a value when we reach the v != null clause.

The rules even incorporate non-local control flow, such as exceptions. For example, if we had:

if (!(x instanceof Foo(var v)) { 
    System.out.println("Not a Foo");
}
B(v);

this would be an error, since v is not guaranteed to have been assigned a value when we reach B(v), but if the if block completes abruptly:

if (!(x instanceof Foo(var v)) { 
    throw new NotFooException();
}
B(v);

then v is in scope at B(v) because we are guaranteed that if we reach that point, v has been assigned a value.

This may look complicated, but it is actually quite simple: given what you know about the flow control of constructs like if, throw, etc, is a pattern variable guaranteed to have been assigned a value at a given point? If so, it is in scope at that point.

like image 197
Brian Goetz Avatar answered Mar 25 '26 16:03

Brian Goetz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!