6

I'm doing something that should be trivial- retrieving an enum value from a property and comparing it with a constant of that enum in an if statement. However Android Studio claims the true case is unreachable code and won't compile.

The block is:

if (ScanState.getScanMode() != ScanState.ScanModeEnum.SCAN_IDLE)
{
    //We're already scanning, but user wants to stop.
    stopScanning();
}
else
{
    ScanState.setScanMode(newMode);
    restartScan();
    buttonFlashMode = btnMode;
    buttonFlasher();
}

where in an extra ScanState class, I have:

public static ScanModeEnum getScanMode() {
    return scanMode;
}

public static void setScanMode(ScanModeEnum scanMode) {
    ScanState.scanMode = scanMode;
}

public enum ScanModeEnum
{
    SCAN_IDLE,
    SCAN_PERSON,
    SCAN_BIKE,
    SCAN_SEARCH
}

private static ScanModeEnum scanMode = ScanModeEnum.SCAN_IDLE;

Variants I've tried, which Android Studio claims will all evaluate to false are

if(ScanState.getScanMode() == ScanState.ScanModeEnum.SCAN_IDLE)
if(ScanState.getScanMode().compareTo(ScanState.ScanModeEnum.SCAN_IDLE)!=0)
if(ScanState.ScanModeEnum.SCAN_IDLE == ScanState.ScanModeEnum.SCAN_IDLE)
if(ScanState.ScanModeEnum.SCAN_IDLE.equals(ScanState.ScanModeEnum.SCAN_IDLE))

I'm new to Java (more familiar with C#), but an answer to this question suggests that my understanding of this is sound. Is there some stupid mistake I'm making?

Community
  • 1
  • 1
Craig Graham
  • 1,161
  • 11
  • 35
  • since you're not showing the complete method body, there are plenty hypotheses that could explain the error. – Marko Topolnik Jul 23 '15 at 09:45
  • 4
    Rather than presenting snippets, are you able to transform this into a short but complete example? I agree it looks like everything should be reachable... – Jon Skeet Jul 23 '15 at 09:46
  • I don't see any reason why `ScanState.ScanModeEnum.SCAN_IDLE == ScanState.ScanModeEnum.SCAN_IDLE` would be false. – Bubletan Jul 23 '15 at 09:46
  • 7
    When I try it in some simple code, everything is reachable – Will Bobo Jul 23 '15 at 09:47
  • Dito. Hard to say. Perhaps the `"ScanState".scanMode = scanMode; `troubles Android studio? Just guessing here. – Florian Schaetz Jul 23 '15 at 09:49
  • 1
    Can confirm will421 here. Copy pasted your code and tried different values for scanMode and managed to land in different branches. Do you maybe set the scanMode to a fixed value before you do the if? –  Jul 23 '15 at 09:50
  • 2
    Maybe you just need to restart the IDE, enable Build Automatically, or other stupid thing related to the environment and not to code. – Marko Topolnik Jul 23 '15 at 09:54

3 Answers3

0

Have you tried debugging this and verifying that the block is never actually reached?

I agree this is a very strange situation. If it persists, I can recommend swapping the enum for int constants, and conducting the check on them. It's not a real fix, but more of a workaround, but at least it can unblock you for the moment.

Danail Alexiev
  • 7,624
  • 3
  • 20
  • 28
0

EDIT: As mentioned by @Bubletan and @MarkoTopolnik, this would not result in a compiler error. Leaving the response as documentation of something that would NOT cause this error.

Do you call anywhere in your code setScanMode? (outside that else block). The compiler may be detecting that the static variable scanMode is never modified, and therefore ScanState.getScanMode() is always ScanState.ScanModeEnum.SCAN_IDLE, thus code not reachable. Try invoking setScanMode somewhere in your code (with a value different than ScanState.ScanModeEnum.SCAN_IDLE) and see if this error disappears.

Jose Gómez
  • 3,110
  • 2
  • 32
  • 54
  • 1
    I don't think so. It's a public method and therefore it could be called anywhere, even from a code which hasn't been written yet. – Bubletan Jul 23 '15 at 09:59
  • IntelliJ has no trouble flagging unused public methods. – Marko Topolnik Jul 23 '15 at 10:04
  • @markoTopolnik but they shouldn't result in an error. – Jose Gómez Jul 23 '15 at 10:05
  • 1
    If you're talking about Java compiler errors, then the access level of the method doesn't matter at all. JLS specifies unreachable code within method as error; it doesn't deal with methods not being called. It also doesn't deal with the value of anything except local variables and compile-time constants. – Marko Topolnik Jul 23 '15 at 10:08
0

Good grief. After making a seperate method as suggested and discovering the problem lay elsewhere I had a look further up the code. The complete method was;

public void onScanButtonPress(@ButtonFlashMode int button)
{
    ScanState.ScanModeEnum newMode;
    @ButtonFlashMode int btnMode = 0;

    switch (button)
    {
        case FLASH_BIKE:
            newMode = ScanState.ScanModeEnum.SCAN_BIKE;
            btnMode = FLASH_BIKE;

        case FLASH_PERSON:
            newMode = ScanState.ScanModeEnum.SCAN_PERSON;
            btnMode = FLASH_PERSON;

        default:
            //Unhandled.
            return;
    }

    if (ScanState.getScanMode() != ScanState.ScanModeEnum.SCAN_IDLE)
    {
        //We're already scanning, but user wants to stop.
        stopScanning();
    }
    else
    {
        ScanState.setScanMode(newMode);
        restartScan();
        buttonFlashMode = btnMode;
        buttonFlasher();
    }
}

Since I've forgotten to put break statements in the cases of the switch, it'll always return before the if is ever evaluated. It'll therefore never evaluate to true and so the error is correct- if misleading since it implies (to me at least!) that the if statement does get evaluated. Thanks for the comments, and I figured this was worth leaving (despite being indeed a stupid mistake) because others might be caught out by this.

Craig Graham
  • 1,161
  • 11
  • 35