0

Consider this:

class BlackMage {
    public void castSpell(SPELL_TYPE spellType) {
        Spell spell;

        if (spellType == null)
            return;

        switch(spellType) {
            case FIRE:
                spell = new Fire();
                break;
            case BLIZZARD:
                spell = new Blizzard();
                break;
            case THUNDER:
                spell = new Thunder();
                break;
        }

        // use spell
    }

    enum SPELL_TYPE {
        FIRE,
        BLIZZARD,
        THUNDER
    }
}

Unless I add a default block to the switch and initialize spell there, the compiler will complain about spell not being initialized. I don't understand why, since we handled all 3 possibilities.

  • You said you have 3 case, but compiler do not sure about that, who knows you will pass the value out of 3 case or not. If for some reason you but a value out of 3 case in here then the `spell` is not initialized – TuyenNTA Aug 04 '17 at 22:24
  • because java enum switch is not exhaustive – luk2302 Aug 04 '17 at 22:24
  • @user2478398 Even if I treat null it will still complain. See edit. –  Aug 04 '17 at 22:25
  • @luk2302 Not being exhaustive means the compiler won't enforce handling every enum value. But since I handled every possible enum value, this should work. –  Aug 04 '17 at 22:27
  • 4
    Suppose your enum is in a library called `a.jar` and this code is in `b.jar`. The creators of `a.jar` publish a new version with a new enum value. Since `b.jar` won't be recompiled, now we have an uninitialized variable case, which should never be allowed. – Edwin Dalorzo Aug 04 '17 at 22:30
  • It obviously means that you need to treat the case where your variable is not any of your cases. Might not possible, because you have a case for every enum item, but the compiler won't check for that. – Tom Aug 04 '17 at 22:31
  • @MS Prima Vista: yes, but they're handled differently. In the same way if you do 'if (x) else if (!x)' you'll still get a complaint if you don't have a final else or something outside of the conditional. One reason being if this code is run against a later version of 'SPELL_TYPE' (which has new spells added), you wouldn't define any return for these new values. – BeUndead Aug 04 '17 at 22:35
  • 1
    @EdwinDalorzo Hmm that makes sense. –  Aug 04 '17 at 22:44
  • Side note: enums should be named like any other type, e.g. `SpellType`. – shmosel Aug 04 '17 at 22:58
  • In general, switching on an enum is somewhat of an antipattern. Consider defining an abstract method to create the `Spell` instance, with each enum instance implementing it appropriately. – shmosel Aug 04 '17 at 23:00
  • Reopening because this is about an enum switch covering all possibilities, not an int which could be any value. – shmosel Aug 04 '17 at 23:11
  • @shmosel I don't know what was on my mind when I wrote that enum name. –  Aug 05 '17 at 02:43
  • @shmosel It doesn't matter if you switch over an enum or an int, OP needs a `default` case and the answer tells him that. – Tom Aug 05 '17 at 06:34
  • @Tom OP is obviously aware of that. The question was *why*. – shmosel Aug 06 '17 at 04:29

1 Answers1

2

The compiler doesn't go to the level of checking how many values your enumeration has.

Your switch doesn't have a default case, that will remove the error. Either replace the last case with default, or simply add an additional default block which assigns any random value; you know it will never evaluate but the compiler doesn't.

MeterLongCat
  • 228
  • 2
  • 11