Search code examples
javavariables

Variable y might not have been initialised in the if's in the loop


import java.util.Scanner;
public class RPS
{
public void show()
{
    int i;
    System.out.println("1 - Rock          2 - Paper        3 - Scissor");
    Scanner in = new Scanner(System.in);
    i = in.nextInt();
    double x = Math.random();
    int y;
    if(x<=0.33)
    {
        y=1;
    }
    else if(x>0.33 && x<0.67)
    {
        y=2;
    }
    else if(x>=0.67)
    {
        y=3;
    }
    for(;;)    
    {
        if(i==y)
        System.out.println("It's a draw!");
        else if(i==1 && y==2)
        System.out.println("Computer wins!");
        else if(i==1 && y==3)
        System.out.println("You win!");
        else if(i==2 && y==1)
        System.out.println("You win!");
        else if(i==2 && y==3)
        System.out.println("Computer wins!");
        else if(i==3 && y==1)
        System.out.println("Computer wins!");
        else if(i==3 && y==2)
        System.out.println("You win!");
        else
        System.out.println("Error!");
    }
    }
 }

Whats wrong? It gives an error that variable y might not have been intialised in the if's in the for loop. I have assigned a value to y in the previous if-else section. so why isnt it getting intialised?


Solution

  • javac is not smart enough to realize that the way your conditions are constructed, one of them will always be true.

    You can rewrite your if-statements to make javac realize one branch will always be triggered:

    int y;
    if(x<=0.33)
    {
        y=1;
    }
    else if(x>0.33 && x<0.67)
    {
        y=2;
    }
    else // This only triggers when x >= 0.67, so no need to check
    {
        y=3;
    }
    

    Now javac sees that if the first two don't trigger, the last will, so y will always have a value.

    You can alternatively add an else branch with an error, in case someone breaks the conditions:

    int y;
    if(x<=0.33)
    {
        y=1;
    }
    else if(x>0.33 && x<0.67)
    {
        y=2;
    }
    else if(x >= 0.67)
    {
        y=3;
    }
    else 
    {
        // This should never happen
        throw new IllegalArgumentException("Something's gone terribly wrong for " + x);
    }
    

    This also compiles, and if someone later decides to skew the numbers and turns the first condition into x <= 0.2 but forgets to update the other condition, you'll get an exception at runtime.