admin管理员组

文章数量:1291041

As I am preparing for OCPJP 21, came across Flow scoping topic.

i need some guidance understanding the concept. below is the code snippet

public class Question28 {
    
    static void getFish(Object fish) {            
        if(!(fish instanceof String guppy))
            System.out.println("Eat!");
        else if(!(fish instanceof String guppy)) {
            throw new RuntimeException();    
        }    
        System.out.println(guppy);    
        System.out.println("Swim!");
    }
    
    public static void main(String args[]) {    
        getFish("ashish");    
    } 
    
}
 

above snippet results into "Cannot find symbol" for variable guppy. but if i remove the else keyword, like below. guppy variable remains in scope. no compiler error.

static void getFish(Object fish) {  
    if(!(fish instanceof String guppy))
        System.out.println("Eat!");
     if(!(fish instanceof String guppy)) {
        throw new RuntimeException();    
    }    
    System.out.println(guppy);
}

my second observation as follows ref snippet

class Sample2 {
    
    static void printNumberTwice(Number number) {    
        if(!(number instanceof Integer data)) 
             return ;
            //System.out.println("Eat!");
    
        System.out.println(data.intValue());    
    }
    
    public static void main(String args[]) {    
        printNumberTwice(5);
    }
}

above snippet successfully compiles but if I comment out return and instead add SOP statement, it results into cannot find symbol for data.

please guide me to understand the concept.

As I am preparing for OCPJP 21, came across Flow scoping topic.

i need some guidance understanding the concept. below is the code snippet

public class Question28 {
    
    static void getFish(Object fish) {            
        if(!(fish instanceof String guppy))
            System.out.println("Eat!");
        else if(!(fish instanceof String guppy)) {
            throw new RuntimeException();    
        }    
        System.out.println(guppy);    
        System.out.println("Swim!");
    }
    
    public static void main(String args[]) {    
        getFish("ashish");    
    } 
    
}
 

above snippet results into "Cannot find symbol" for variable guppy. but if i remove the else keyword, like below. guppy variable remains in scope. no compiler error.

static void getFish(Object fish) {  
    if(!(fish instanceof String guppy))
        System.out.println("Eat!");
     if(!(fish instanceof String guppy)) {
        throw new RuntimeException();    
    }    
    System.out.println(guppy);
}

my second observation as follows ref snippet

class Sample2 {
    
    static void printNumberTwice(Number number) {    
        if(!(number instanceof Integer data)) 
             return ;
            //System.out.println("Eat!");
    
        System.out.println(data.intValue());    
    }
    
    public static void main(String args[]) {    
        printNumberTwice(5);
    }
}

above snippet successfully compiles but if I comment out return and instead add SOP statement, it results into cannot find symbol for data.

please guide me to understand the concept.

Share Improve this question edited Feb 18 at 15:39 Marce Puente 5753 silver badges12 bronze badges asked Feb 13 at 16:57 Ashish ParabAshish Parab 1983 silver badges22 bronze badges 1
  • There is no need to have another instanceof test in the else if clause; since the test is identical to the previous one, simply negated, else is sufficient. The guppy variable is only valid from the point it is mentioned to the end of the if block. – David Conrad Commented Feb 13 at 17:47
Add a comment  | 

1 Answer 1

Reset to default 1

You can only use the variable if the compiler can proof that the code is only executed if the pattern matches.

Now, let's look at your example:

if(!(fish instanceof String guppy))
    System.out.println("Eat!");
else if(!(fish instanceof String guppy)) {
    throw new RuntimeException();
}
System.out.println(guppy);

Let's say fish is not a String. In this case, it would enter the if statement printing Eat!. Since it entered the if, it doesn't enter the else if so it would continue trying to print guppy - But wait it is no String so guppy might not exist (it isn't definitely assigned).

If you skip the else keyword, you are always throwing the exception if fish isn't a String. There, you only allow execution for Strings enduring that guppy is valid.

Now, let's also check your second example:

if(!(number instanceof Integer data)) 
    return;
    //System.out.println("Eat!");
System.out.println(data.intValue());

Here, you can use data because the compiler provably knows that number is an Integer. If it isn't, the execution flow would be cancelled/stopped by the return statement (which can also be done using exceptions, break; or continue;).

If you remove the return and replace it with a statement not impacting control flow, passing non-Strings could cause the System.out.println to be executed.

That being said, please note that the Java compiler is not a powerful theorem-prover and doesn't try to be. It does some work to detect whether variables are assigned but it isn't complete (which would be impossible thanks to Gödel) i.e. there are cases where it's impossible that a statement is executed but the compiler doesn't know. The important thing the compiler focuses is soundness i.e. ensuring that it doesn't allow invalid code (and being predictable and following the specification).

本文标签: FlowScoping in java 21Stack Overflow