JDK-6191812 : Ability to use qualified enums in case statements
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_2000,windows_xp
  • CPU: x86
  • Submitted: 2004-11-06
  • Updated: 2010-04-04
  • Resolved: 2006-11-06
Related Reports
Relates :  
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
  Today only unqualified enum constants may be used in select/case statements, and it is not permitted to use qualified enum constants. This is inconsistent with other data access alternatives in Java, and may lead to confusion.

JUSTIFICATION :
Allow the use of qualified enum constants in switch/case statements to be consistent  with the ability to use qualified constants.

The enums themselves are also inconsistent in behaviour, since they currently allow for qualified access in if-statements, but not in switch/case statements.

Another reason is that enums with the same name, but with different meaning can be imported from different classes (not unheard of when integrating different software packages). In this case qualified access to enum constants is necessary.


In the test case below, the compiler complains because the case statements refer to qualified Enums.  Replacing
            case EnumClass.Action.ADD:
with 
            case ADD:

allows the test to pass.


---------- BEGIN SOURCE ----------
File EnumClass.java:
------------------------------
public class EnumClass
{
    public enum Action { ADD, UPDATE, DELETE }

    public EnumClass()
    {
    }

    public Action getAction()
    {
        return Action.ADD;
    }
}
------------------------------

File TestClass.java:
---------------------------
public class TestClass
{

    public static void main(String[] args)
    {
        EnumClass ec=new EnumClass();

        EnumClass.Action action=ec.getAction();

        switch(action)
        {
            case EnumClass.Action.ADD:
                System.out.println("Add!");
                break;
            case EnumClass.Action.UPDATE:
                System.out.println("Update!");
                break;
            case EnumClass.Action.DELETE:
                System.out.println("Delete!");
                break;
        }
    }
}


---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Two methods are possible:

Use of "import enumtest.EnumClass.Action.*;" (example above) and unqualified access to enum constants.

Use of if-statements where qualified access is permitted.
###@###.### 2004-11-06 00:38:38 GMT

Comments
EVALUATION The rule for switch ensures that an enum value (the expression) can only be compared with the enum constants (the case labels) from its own enum declaration. This is convenient, because you cannot compare a value of enum type E1 with constants from enum type E2: enum Season { SPRING,SUMMER,AUTUMN,WINTER } enum QuarterOfYear { FIRST,SECOND,THIRD,FOURTH } Season s; switch (s) { case QuarterOfYear.FIRST ... // Wrong to compare Season with QuarterOfYear; disallowed } You say "Another reason is that enums with the same name, but with different meaning can be imported from different classes (not unheard of when integrating different software packages). In this case qualified access to enum constants is necessary." - if you mean that there are two enum declarations named Season, one from CompanyA and one from CompanyB, then having a switch like: switch (s) { case com.CompanyA.Season.SUMMER : // Fall through... case com.CompanyB.Season.SUNNY : // Do something when the weather is nice } or even: switch (s) { case com.CompanyA.Season.SPRING : // Do one thing case com.CompanyB.Season.SPRING : // Do a different thing } is possible, but whether s is a com.CompanyA.Season or a com.CompanyB.Season is always known statically, so leaving extra case clauses around is not good practice. Furthermore, switch is special because the case labels are constants, unlike the (sub)expressions in a conditional expression. While a conditional must always compare an enum value of type E1 with another enum value of type E1, the enum values in a conditional need not be constants; they can be in variables, so qualifying with an enum name is wrong. Using the Season enum from above: Season s = Season.SPRING; if (s == Season.SUMMER) ... // A legal test Season SOMESEASON = chooseSeason(); if (s == SOMESEASON) ... // Also a legal test if (s == SUMMER) ... // *IF* this was legal, would SUMMER mean Season.SUMMER on the grounds that s is of type Season, or would SUMMER mean a local variable called SUMMER? What are the rules for disambiguating in this case? Not something we want to get into.
06-11-2006