Case expression must be constant expression

Discussion in 'Java' started by Philipp, Nov 22, 2007.

  1. Philipp

    Philipp Guest

    Hello,
    I don't understand why the following code gives a compilation error. In
    the "case" statements, the compiler complains that "Case expression must
    be constant expression", but as far as I can see, the expression are
    constant.

    Thanks for any comments
    Phil


    --- SSCCE ---

    public class SwitchTest {
    public final int a = 1;
    public final int b = 2;
    public final int c = 3;

    public SwitchTest() {}

    public static void main(String[] args) {
    SwitchTest object = new SwitchTest();

    int choice = 2;

    switch(choice){
    case object.a:
    System.out.println("a");
    break;
    case object.b:
    System.out.println("b");
    break;
    case object.c:
    System.out.println("c");
    break;
    default:
    System.out.println("other");
    }
    }
    }
    Philipp, Nov 22, 2007
    #1
    1. Advertising

  2. Philipp

    Stefan Ram Guest

    Stefan Ram, Nov 22, 2007
    #2
    1. Advertising

  3. Philipp

    bugbear Guest

    Philipp wrote:
    > Hello,
    > I don't understand why the following code gives a compilation error. In
    > the "case" statements, the compiler complains that "Case expression must
    > be constant expression", but as far as I can see, the expression are
    > constant.
    >
    > Thanks for any comments
    > Phil
    >
    >
    > --- SSCCE ---
    >
    > public class SwitchTest {
    > public final int a = 1;
    > public final int b = 2;
    > public final int c = 3;


    I believe (too lazy to check)
    that only "static final" is deemed a full blown constant
    by the language/compiler.

    BugBear
    bugbear, Nov 22, 2007
    #3
  4. On Thu, 22 Nov 2007 13:39:13 +0100, Philipp wrote:
    > I don't understand why the following code gives a compilation error.
    > In the "case" statements, the compiler complains that "Case
    > expression must be constant expression", but as far as I can see,
    > the expression are constant.


    Well, "object" in your example is not a compile-time constant. If your
    lables had been static, then you could have specified them as
    "SwitchTest.a" etc.

    See section 15.28 in the JLS for the relevant definition:
    http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.28

    /gordon

    --
    Gordon Beaton, Nov 22, 2007
    #4
  5. Stefan Ram wrote:
    > Philipp <> writes:
    >> but as far as I can see, the expression are constant.

    >
    > As far as I can see, the expression are not on the list
    > as given in:
    >
    > »15.28 Constant Expression«
    >
    > http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.28
    >


    But would be on the list if the fields a, b, and c were static as well
    as final.

    Non-static fields, even if declared final, can have different values for
    different instances of the class.

    Patricia
    Patricia Shanahan, Nov 22, 2007
    #5
  6. Philipp

    Guest

    On Nov 22, 7:52 pm, Patricia Shanahan <> wrote:
    > Stefan Ram wrote:
    > > Philipp <> writes:
    > >> but as far as I can see, the expression are constant.

    >
    > > As far as I can see, the expression are not on the list
    > > as given in:

    >
    > > >>15.28 Constant Expression<<

    >
    > >http://java.sun.com/docs/books/jls/third_edition/html/expressions.htm...

    >
    > But would be on the list if the fields a, b, and c were static as well
    > as final.
    >
    > Non-static fields, even if declared final, can have different values for
    > different instances of the class.
    >
    > Patricia


    Hi
    if u see u are giving object.a, but object is an instance
    variable...its just stores the address. Similarly if u keep a string
    in a switch case...it will give u a compilation error...because switch
    doesnot allow instance variables...in ur code u declared c as int and
    gave a value as 2 which is a primitive datatype..but in "case" u are
    refering to an instance..so it wont take ur code...
    , Nov 22, 2007
    #6
  7. Philipp

    Lew Guest

    wrote:
    > if u see u are giving object.a, but object is an instance
    > variable...its just stores the address. Similarly if u keep a string
    > in a switch case...it will give u a compilation error...because switch
    > doesnot allow instance variables...in ur code u declared c as int and
    > gave a value as 2 which is a primitive datatype..but in "case" u are
    > refering to an instance..so it wont take ur code...


    Just a gentle suggestion - please take the care to use full words and spacing.
    Txtspeek is awful stuff and looks unbelievably illiterate. It also makes
    the message harder to read.

    --
    Lew
    Lew, Nov 22, 2007
    #7
  8. Philipp

    Roedy Green Guest

    Roedy Green, Nov 23, 2007
    #8
  9. Philipp

    Philipp Guest

    Roedy Green wrote:
    > On Thu, 22 Nov 2007 13:39:13 +0100, Philipp <>
    > wrote, quoted or indirectly quoted someone who said :
    >
    >> "Case expression must
    >> be constant expression", but as far as I can see, the expression are
    >> constant.

    >
    > By "constant", they don't mean final. they mean "known at compile
    > time". They mean literals or compile time constants.
    >
    > See http://mindprod.com/jgloss/literal.html
    > http://mindprod.com/jgloss/constant.html
    >


    Hello
    On your very clear and understandable page
    http://mindprod.com/jgloss/constant.html (which IMHO is not the case of
    the JLS), you write:

    4. Instance Constants: <snip>
    It is sometimes possible for an instance constant to be evaluated at
    compile time. In that case it is treated like a literal, much like a
    static compile-time constant.

    Isn't this exactly the case of my example in the original post? Isn't it
    an instance constant which can be evaluated at compile time?

    Btw, I wanted to use a switch in my code, but due to these limitation
    it's now a if/else stack...

    Best regards
    Phil
    Philipp, Nov 23, 2007
    #9
  10. Philipp

    Lew Guest

    Philipp wrote:
    > On your very clear and understandable page
    > http://mindprod.com/jgloss/constant.html (which IMHO is not the case of
    > the JLS), you write:


    The purpose of the JLS is not expository, it's to be precise and unambiguous.
    In particular, it specifies how a Java compiler must behave.

    It is useful when one wants to know exactly what's what in the language, less
    so for learning the concepts until you get used to it. Then it's priceless.

    --
    Lew
    Lew, Nov 23, 2007
    #10
  11. On Nov 23, 1:37 am, Philipp <> wrote:
    > Roedy Green wrote:
    > > On Thu, 22 Nov 2007 13:39:13 +0100, Philipp <>
    > > wrote, quoted or indirectly quoted someone who said :

    >
    > >> "Case expression must
    > >> be constant expression", but as far as I can see, the expression are
    > >> constant.

    >
    > > By "constant", they don't mean final. they mean "known at compile
    > > time". They mean literals or compile time constants.

    >
    > > Seehttp://mindprod.com/jgloss/literal.html
    > >http://mindprod.com/jgloss/constant.html

    >
    > Hello
    > On your very clear and understandable pagehttp://mindprod.com/jgloss/constant.html(which IMHO is not the case of
    > the JLS), you write:
    >
    > 4. Instance Constants: <snip>
    > It is sometimes possible for an instance constant to be evaluated at
    > compile time. In that case it is treated like a literal, much like a
    > static compile-time constant.
    >
    > Isn't this exactly the case of my example in the original post? Isn't it
    > an instance constant which can be evaluated at compile time?


    The specific example you showed, repeated here for clarity:

    public final int a = 1;

    ....
    switch (someInt) {
    case object.a:
    ....

    does not meet the definition of the phrase "constant expression" as
    defined in the JLS, even though in theory you could determine
    statically that a is always going to be 1 at that point in the code.
    The JLS doesn't demand that level of sophistication from the compiler:
    'object' is not a constant expression, therefore no expression
    containing it can be a constant expression.[0]

    Unless there's some wild deviation between your example and your real
    problem, I don't see why you can't make 'a' static final and refer to
    it as SwitchTest.a or some similar form. What're you working on?
    Maybe someone has a better suggestion than an if ladder.

    [0] It's probably worth mentioning here that the ONLY reference type
    allowed in a constant expression is String. No other class can have
    constant values according to the JLS. Since String is the only class
    that can be instantiated without a 'new', this makes some sense.
    Owen Jacobson, Nov 23, 2007
    #11
  12. Philipp

    Lew Guest

    Owen Jacobson wrote:
    > Since String is the only class that can be instantiated without a 'new'


    int [] nums = { 1, 3, 5, 7 };

    --
    Lew
    Lew, Nov 23, 2007
    #12
  13. Philipp

    Roedy Green Guest

    On Fri, 23 Nov 2007 04:40:00 -0500, Lew <> wrote,
    quoted or indirectly quoted someone who said :

    >The purpose of the JLS is not expository, it's to be precise and unambiguous.
    > In particular, it specifies how a Java compiler must behave.


    If it is too obscure, it fails in doing that. If it were peppered
    with a sufficient examples to illustrate each point, it would be much
    less ambiguous and more accessible. English is much less precise than
    a carefully chosen example set. The problem is even reasonably
    competent people can read the JLS and differ on what it means, or feel
    unsure they know what it means.

    You want examples guaranteed to give a certain result or guaranteed to
    give an error message.

    This has been a bugbear of mine since university days. I have often
    accused profs of making the simple sound complicated in order to
    impress rather than inform. Did you ever read the Algol 68 report? It
    is a classic case.

    Another would be legal agreements that companies get their customers
    to sign. They are deliberately written so that customers have no idea
    what they are agreeing to. Look how many people bought "fire
    insurance" and discovered it did not compensate them in the California
    fires.

    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
    Roedy Green, Nov 23, 2007
    #13
  14. Philipp

    Roedy Green Guest

    On Fri, 23 Nov 2007 10:37:37 +0100, Philipp <>
    wrote, quoted or indirectly quoted someone who said :

    >Isn't this exactly the case of my example in the original post? Isn't it
    > an instance constant which can be evaluated at compile time?


    nope.

    SwitchTest object = new SwitchTest();

    int choice = 2;

    switch(choice){
    case object.a:

    The address of object is not known until the program runs. The
    object.a does not exist at compile time.

    had you written:

    public static final int a = 1;
    public static final int b = 2;
    public static final int c = 3;
    ....
    switch(choice){
    case a:
    or
    case SwitchTest.a:

    then the value would be known at compile time.

    Had you left out the static, I don't know what would happen. The
    compiler might say NO on the grounds it does not know the value of any
    fields in an object at compile time. The compiler might say OK, on
    the grounds, it can deduce the values, even at compile time.

    From a practical point of view, there is no point in leaving out the
    static when the value is known at compile time. The only point in an
    instance constant is when the value differs for each instance of the
    object, or its value cannot be determined until the object is
    instantiated.

    Java literature does not make as clean a distinction between the seven
    flavours of constant as I would like.

    It is presented as a vague soup. You figure it out on your own by
    discovering what the compiler will eat.

    If you follow these rules of thumb, you will get by without having to
    fully understand constants:

    Avoid literals other than 0 and 1. Use static finals instead.

    If a value can be known at compile or load time, mark it static final.
    If a value does not change after you compute it, mark it final. This
    applies to static variables, instance variables, local variables and
    parameters.

    If in doubt whether a value is ok for a case, try it. If the compiler
    does not complain, it was ok.

    If your constants need to be computed in some special order, put that
    initialisation in a static {} or an instance intialisation {} block
    where the order won't be meddled with. Don't trust the order of
    declarations. Some tidying program such as IntelliJ Idea Rearranger
    will eventually disturb the variable declaration order leaving you or
    someone else baffled why the initialisation no longer works.

    If you change the value of a static final, do a clean recompile of all
    places it is used to propagate the new value.
    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
    Roedy Green, Nov 23, 2007
    #14
  15. Philipp wrote:
    > Roedy Green wrote:
    >> On Thu, 22 Nov 2007 13:39:13 +0100, Philipp <>
    >> wrote, quoted or indirectly quoted someone who said :
    >>
    >>> "Case expression must be constant expression", but as far as I can
    >>> see, the expression are constant.

    >>
    >> By "constant", they don't mean final. they mean "known at compile
    >> time". They mean literals or compile time constants.
    >>
    >> See http://mindprod.com/jgloss/literal.html
    >> http://mindprod.com/jgloss/constant.html
    >>

    >
    > Hello
    > On your very clear and understandable page
    > http://mindprod.com/jgloss/constant.html (which IMHO is not the case of
    > the JLS), you write:


    The JLS is the authoritative description of the language, and as such
    has to be extremely precise. It is often very difficult, if not
    impossible, to explain things both precisely and simply.


    > 4. Instance Constants: <snip>
    > It is sometimes possible for an instance constant to be evaluated at
    > compile time. In that case it is treated like a literal, much like a
    > static compile-time constant.
    >
    > Isn't this exactly the case of my example in the original post? Isn't it
    > an instance constant which can be evaluated at compile time?


    I think the quote may relate to optimizations that the compiler can
    choose to do without changing the language. Your code would require a
    change in the Java language, away from what the JLS specifies.

    >
    > Btw, I wanted to use a switch in my code, but due to these limitation
    > it's now a if/else stack...


    I don't understand why you did that. Your original code would have
    worked fine if you had added "static" to each of the declarations:

    public static final int a = 1;
    public static final int b = 2;
    public static final int c = 3;

    Given the "final" and the constant initializer, I don't see any benefit
    to having a separate copy of each variable for each object of your
    class, rather than a single copy shared by all objects.

    There is a subset of switch situations that every compiler can implement
    faster or more compactly than their if-then-else equivalent. The Java
    designers choose to limit the switch syntax to those situations.

    However, I would have preferred it if they had allowed unrestricted
    switch, allowing any expressions and any type, using == comparison for
    primitives and equals() method for references.

    At the worst, the compiler would generate a sequential if-then-else
    stack, the same code as you converted to. The other implementations
    would be optimizations relative to that code.

    Patricia
    Patricia Shanahan, Nov 23, 2007
    #15
  16. Roedy Green wrote:
    > On Fri, 23 Nov 2007 04:40:00 -0500, Lew <> wrote,
    > quoted or indirectly quoted someone who said :
    >
    >> The purpose of the JLS is not expository, it's to be precise and unambiguous.
    >> In particular, it specifies how a Java compiler must behave.

    >
    > If it is too obscure, it fails in doing that. If it were peppered
    > with a sufficient examples to illustrate each point, it would be much
    > less ambiguous and more accessible. English is much less precise than
    > a carefully chosen example set. The problem is even reasonably
    > competent people can read the JLS and differ on what it means, or feel
    > unsure they know what it means.


    Occasionally, one can get a better idea by reading the VM spec; the
    details of protected access, IMO, is an example where the VM spec is
    clearer than the JLS.

    Still, the JLS could use with some more examples; it gives some examples
    where none are needed and leaves out some where one or more is needed.

    --
    Beware of bugs in the above code; I have only proved it correct, not
    tried it. -- Donald E. Knuth
    Joshua Cranmer, Nov 23, 2007
    #16
  17. Philipp

    Lew Guest

    Roedy Green wrote:
    > Java literature does not make as clean a distinction between the seven
    > flavours of constant as I would like.


    There are seven?

    --
    Lew
    Lew, Nov 23, 2007
    #17
  18. On Nov 23, 2:15 am, Lew <> wrote:
    > Owen Jacobson wrote:
    > > Since String is the only class that can be instantiated without a 'new'

    >
    > int [] nums = { 1, 3, 5, 7 };


    Drat! Thanks Lew.

    Ok, so Strings are special in other ways: array literals cause new
    objects to be constructed every time the expression is evaluated at
    runtime and String literals do not. :)

    -Owen
    Owen Jacobson, Nov 23, 2007
    #18
  19. Philipp

    Lew Guest

    Owen Jacobson wrote:
    > On Nov 23, 2:15 am, Lew <> wrote:
    >> Owen Jacobson wrote:
    >>> Since String is the only class that can be instantiated without a 'new'

    >> int [] nums = { 1, 3, 5, 7 };

    >
    > Drat! Thanks Lew.
    >
    > Ok, so Strings are special in other ways: array literals cause new
    > objects to be constructed every time the expression is evaluated at
    > runtime and String literals do not. :)


    The array instantiation example is completely irrelevant to the point you were
    making, that Strings can be compile-time constants, but I couldn't resist
    tweaking you a little there.

    --
    Lew
    Lew, Nov 23, 2007
    #19
  20. Philipp

    Daniel Pitts Guest

    Philipp wrote:
    > Roedy Green wrote:
    >> On Thu, 22 Nov 2007 13:39:13 +0100, Philipp <>
    >> wrote, quoted or indirectly quoted someone who said :
    >>
    >>> "Case expression must be constant expression", but as far as I can
    >>> see, the expression are constant.

    >>
    >> By "constant", they don't mean final. they mean "known at compile
    >> time". They mean literals or compile time constants.
    >>
    >> See http://mindprod.com/jgloss/literal.html
    >> http://mindprod.com/jgloss/constant.html
    >>

    >
    > Hello
    > On your very clear and understandable page
    > http://mindprod.com/jgloss/constant.html (which IMHO is not the case of
    > the JLS), you write:
    >
    > 4. Instance Constants: <snip>
    > It is sometimes possible for an instance constant to be evaluated at
    > compile time. In that case it is treated like a literal, much like a
    > static compile-time constant.
    >
    > Isn't this exactly the case of my example in the original post? Isn't it
    > an instance constant which can be evaluated at compile time?
    >
    > Btw, I wanted to use a switch in my code, but due to these limitation
    > it's now a if/else stack...
    >
    > Best regards
    > Phil

    Just a note, have you considered using enums or even use a polymorphic
    object instead of switch?

    <http://virtualinfinity.net/wordpress/program-design/2007/10/22/using-enums-as-a-flyweight-pattern/>

    In Object Oriented design, its considered a likely problem if you have a
    switch statement (or a switch like construct). While there are *some*
    times when a switch is appropriate, I've found that I haven't used a
    switch statement once I understood the State, Strategy, and Flyweight
    patterns.

    As an aside more direct to your original post, is there a good reason to
    make them *not* static final int?

    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Nov 23, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mohammed  A khader
    Replies:
    1
    Views:
    2,562
    Jonathan Bromley
    Jan 28, 2005
  2. PB
    Replies:
    10
    Views:
    6,567
    Dave Thompson
    Mar 27, 2006
  3. Replies:
    13
    Views:
    12,884
    Kai-Uwe Bux
    Jan 22, 2007
  4. Adem
    Replies:
    42
    Views:
    2,773
    James Kuyper
    Nov 4, 2008
  5. Adem
    Replies:
    45
    Views:
    1,735
    James Kuyper
    Nov 4, 2008
Loading...

Share This Page