Case expression must be constant expression

P

Philipp

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");
}
}
}
 
B

bugbear

Philipp said:
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
 
G

Gordon Beaton

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

--
 
C

chinmoy.titan

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

Lew

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

Philipp

Roedy said:
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
 
L

Lew

Philipp said:
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.
 
O

Owen Jacobson

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

Roedy Green

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

Roedy Green

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

Patricia Shanahan

Philipp said:
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
 
J

Joshua Cranmer

Roedy said:
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.
 
O

Owen Jacobson

Owen said:
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
 
L

Lew

Owen said:
Owen said:
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.
 
D

Daniel Pitts

Philipp said:
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?
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top