Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / November 2007

Tip: Looking for answers? Try searching our database.

Case expression must be constant expression

Thread view: 
Philipp - 22 Nov 2007 12:39 GMT
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");
    }
  }
}
Stefan Ram - 22 Nov 2007 12:45 GMT
>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
Patricia Shanahan - 22 Nov 2007 14:52 GMT
>> but as far as I can see, the expression are constant.
>
[quoted text clipped - 4 lines]
>
> 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
chinmoy.titan@gmail.com - 22 Nov 2007 14:59 GMT
> >> but as far as I can see, the expression are constant.
>
[quoted text clipped - 12 lines]
>
> 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...
Lew - 22 Nov 2007 15:08 GMT
> 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.

Signature

Lew

Ramon F Herrera - 25 Nov 2007 22:10 GMT
> chinmoy.ti...@gmail.com wrote:
> > if u see u are giving object.a, but object is an instance
[quoted text clipped - 10 lines]
> --
> Lew

I agree with you, Lew. It seems that we have a whole generation of
people who has learned how to type on cell phones and IMs!

-Ramon
bugbear - 22 Nov 2007 12:45 GMT
> Hello,
> I don't understand why the following code gives a compilation error. In
[quoted text clipped - 11 lines]
>   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
Gordon Beaton - 22 Nov 2007 12:51 GMT
> 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

--
Roedy Green - 23 Nov 2007 08:34 GMT
>"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

Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Philipp - 23 Nov 2007 09:37 GMT
>> "Case expression must
>> be constant expression", but as far as I can see, the expression are
[quoted text clipped - 5 lines]
> 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
Lew - 23 Nov 2007 09:40 GMT
> 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.

Signature

Lew

Roedy Green - 23 Nov 2007 10:59 GMT
>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.

Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Joshua Cranmer - 23 Nov 2007 16:10 GMT
>> 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.
[quoted text clipped - 5 lines]
> 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.

Signature

Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Roedy Green - 24 Nov 2007 08:30 GMT
On Fri, 23 Nov 2007 10:59:17 GMT, Roedy Green
<see_website@mindprod.com.invalid> wrote, quoted or indirectly quoted
someone who said :

>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.

We studied proof after proof in mathematics, but we never saw how one
was actually constructed. It was like studying building construction
without ever seeing anything but a completed building.  Mathematicians
were embarrassed about the way intuition and refinement went into a
polished elegant, minimalist proof. They wanted to hide every trace
the scaffolding had ever existed.

Similarly when we were studying group and ring theory, the profs would
smack us down if we ever tried to think about concrete examples
worked. This would contaminate your thinking they asserted.  You would
make unwarranted assumptions that applied only to special cases. They
wanted you to argue and think purely from the abstract.  I could see
insisting your final proof was purely abstract, but I could not see
why it was so wicked to use concrete examples to give your mind
something concrete to think about.

As a kid I used to sell "cheat sheets" to fellow students for 5 cents
each to give them rules of thumb, and intuitive hooks to help them
solve math, physics, chemistry and genetics problems. Human problem
solving is a sloppier trial-and-error business than we pretend.  

One beauty of the Internet is anyone is free to compose instructional
materials with any degree of informality they please.

My contention is humans are superb at generalising from a well-chosen
set of examples. This is much easier than absorbing abstract rules.
This is what you would expect since experience teaches by example.
This is how all animals learn. Very rarely do you get presented with
an abstract theory.  Consider how much easier arithmetic is for a
calculator than for a human.  We humans are relatively inept even at
applying the relatively simple rules of arithmetic.

Yet a human can solve a difficult problem like who would make a
suitable roommate, one that can be thought of as reasoning from many
examples.

Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Owen Jacobson - 23 Nov 2007 10:08 GMT
> >> "Case expression must
> >> be constant expression", but as far as I can see, the expression are
[quoted text clipped - 17 lines]
> 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.
Lew - 23 Nov 2007 10:15 GMT
> Since String is the only class that can be instantiated without a 'new'

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

Signature

Lew

Owen Jacobson - 23 Nov 2007 17:21 GMT
> > 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
Lew - 23 Nov 2007 17:36 GMT
>>> Since String is the only class that can be instantiated without a 'new'
>>   int [] nums = { 1, 3, 5, 7 };
[quoted text clipped - 4 lines]
> 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.

Signature

Lew

Philipp - 24 Nov 2007 13:19 GMT
> What're you working on?
> Maybe someone has a better suggestion than an if ladder.

Yes, actually I was trying to make a replacement for an Enum in JRE 1.3
when I stumbled accross this "Constant in case expression" problem.

What I made to mimic an enum is a class with static final members of
itself inside (see example code below). But in this case I can't use the
ordinal in a switch statement...

Phil

--SSCE--  (notice the missing C :-)

import java.util.HashMap;

public class Month{
  private final int ordinal;
  private static final HashMap correspondanceMap = new HashMap();

  private Month(int ordinal) {
    this.ordinal = ordinal;
    correspondanceMap.put(new Integer(ordinal), this);
  }

  public static final Month JANUARY = new Month(1);
  public static final Month FEBRUARY = new Month(2);
  public static final Month MARCH = new Month(3);
  public static final Month APRIL = new Month(4);

  public int getOrdinal(){
    return ordinal;
  }

  public static Month byOrdinal(int ordinal){
    return (Month)correspondanceMap.get(new Integer(ordinal));
  }

  public int hashCode() { return ordinal; }

  public boolean equals(Object h_type){
    if (!(h_type instanceof Month)) return false;
    if ( ((Month)h_type).getOrdinal() == getOrdinal()) return true;
    else return false;
  }

  public static void main(String[] args) {
    System.out.println("April's ordinal is: " + Month.APRIL.getOrdinal());

    Month m = Month.byOrdinal(2);
    if(m.equals(Month.FEBRUARY)){
      System.out.println("Both are equal.");
    }

    // switch doesn't work
    int choice = 3;
    switch(choice){
    case Month.JANUARY.getOrdinal():
      System.out.println("Do something for January");
    case Month.FEBRUARY.getOrdinal():
      System.out.println("Do something for February");
    case Month.MARCH.getOrdinal():
      System.out.println("Do something for March");
    case Month.APRIL.getOrdinal():
      System.out.println("Do something for April");
    default:
      System.out.println("None of those months");
    }
  }
}
Lew - 24 Nov 2007 13:20 GMT
> Yes, actually I was trying to make a replacement for an Enum in JRE 1.3
> when I stumbled accross this "Constant in case expression" problem.

Check out the "type-safe enum", as explained by Joshua Bloch in /Effective
Java/, for example.

Signature

Lew

Roedy Green - 23 Nov 2007 12:04 GMT
>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.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Lew - 23 Nov 2007 16:35 GMT
> Java literature does not make as clean a distinction between the seven
> flavours of constant as I would like.

There are seven?

Signature

Lew

Roedy Green - 24 Nov 2007 08:32 GMT
>> Java literature does not make as clean a distinction between the seven
>> flavours of constant as I would like.
>
>There are seven?

see http://mindprod.com/jgloss/constant.html

for the seven types. There categories are mine, nothing official in
Java.
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Patricia Shanahan - 23 Nov 2007 14:31 GMT
>>> "Case expression must be constant expression", but as far as I can
>>> see, the expression are constant.
[quoted text clipped - 9 lines]
> 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
[quoted text clipped - 3 lines]
> 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
Daniel Pitts - 23 Nov 2007 17:54 GMT
>>> "Case expression must be constant expression", but as far as I can
>>> see, the expression are constant.
[quoted text clipped - 23 lines]
> 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?

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Ed Kirwan - 24 Nov 2007 09:56 GMT
> 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.

Hej, Daniel,

Would you say that a switch statement is inappropriate in a parameterised
factory method, such as the one below?

http://www.edmundkirwan.com/servlet/fractal/cs1/code/package101.html#getEvaluation

And if inappropriate, how should parameterised factory methods look? Or
would you say that parameterised factory methods are inherently un-OO?

I'm curious because I use them quite a lot and am wondering whether I should
drop them in favour of something else.

Signature

.ed

www.EdmundKirwan.com - Home of encapsulation theory.

Daniel Pitts - 24 Nov 2007 18:30 GMT
>> In Object Oriented design, its considered a likely problem if you have a
>> switch statement (or a switch like construct).  While there are *some*
[quoted text clipped - 14 lines]
> I'm curious because I use them quite a lot and am wondering whether I should
> drop them in favour of something else.

In your example, where does rank come from?
Is it assigned specific values based on another if/else block?

This seems to me to fit my example of using an enum as a flyweight:
<http://virtualinfinity.net/wordpress/program-design/2007/10/22/using-enums-as-a-
flyweight-pattern/
>

Basically, you have a Rank abstract class/interface which has the
implementations HighestCard, OnePair, TwoPairs, etc....

The interface would have a HandEvaluation getEvaluation(Hand hand);
Your factory method could remain.  It would simply delegate to
rank.getEvaluation(hand);

Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.