• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Tim Cooke
  • Campbell Ritchie
  • Ron McLeod
  • Junilu Lacar
  • Liutauras Vilda
Sheriffs:
  • Paul Clapham
  • Jeanne Boyarsky
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Piet Souris
  • Carey Brown
Bartenders:
  • Jesse Duncan
  • Frits Walraven
  • Mikalai Zaikin

switch statement

 
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The JLS says that in a switch statement, the constant expression in the case label should be assignable to the type of the integral expression appearing after the switch keyword.
But in the following code, the integral expression is of type char and the case label value is of type byte. This code compiles and runs without a hitch eventhough values of type byte CANNOT be assigned to variables of type char without an explicit cast!
<CODE>
public class swicht {
public static void main(String[] args) {
char charExpression = 0x41;
final byte b = 0x41;
switch (charExpression) {
default:
System.out.println("default");
break;
case b:
System.out.println("byte - " + b);
break;
}
charExpression = (char)b; // explicit cast needed
System.out.println("charExpression - " + charExpression);
}
}</CODE>
Is there an inconsistency between the specification and the JDK implementation here? I am using JDK 1.2 on Win98. Pls help.
 
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If Java desugners had any design goals, inconsistency was probably the most important.
For example:

charExpression = (char)b; // explicit cast needed
but
charExpression += b;
is OK.
Or:
float f = 2.3; // compile-time error
But float f = 'q'; // compiles fine
WHY? For what reason does compiler reject harmless and meaningful assignment f = 2.3, but doesn't object to strange assugnment f to 'q'? (Do not cite JLS, I know why the first assignment is illegal. I ask for what reason Java designers made it illegal?)
I have more examples...
 
thomas
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I am curious if there is an inconsistency between the JLS and JDK with respect to the switch statement OR if it is some inconsistency in my understanding.
 
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The above code generates a compile error if the value assigned to the byte variable b made to be a negative number. So, I guess the compiler goes by the value that is stored in the byte variable before it decides whether it is an error or not.
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think srikrish is right. Here are some cites from JLS:


15.27 Constant Expression
Compile-time constant expressions are used in case labels in switch statements (�14.9) and have a special significance for assignment conversion (�5.2).
5.2 Assignment Conversion
<...>
In addition, a narrowing primitive conversion may be used if all of the following conditions are satisfied:
* The expression is a constant expression of type int.
* The type of the variable is byte, short, or char.
* The value of the expression (which is known at compile time, because it is a constant expression) is representable in the type of the variable.


BTW, thomas, IMHO some inconsistency in your understanding (and not only in your ) is result of some inconsistency in Java language�
 
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes,Yes: it's curious
according to JLS narrow coversion when expression is constant.
so in switch can execute.
charExpression= 0x41; //ok
charExpression += b; //ok
is this because: charExpression= charExpression + b ? and promotion occur
and
charExpression= b;
from the error display, compiler do not think b is constant.
i canot understant srikrish's meaning.
and Mapraputa Is :
float f = 2.3 //error because narrow convert double to float
But float f = 'q'; //ok because widen convet from char to float
so is this realy inconsent between jls and jdk?
michael

[This message has been edited by michael huang (edited September 18, 2000).]
 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The whole point here would be in understanding of a certian thing by practise. There have been many inconsistencies as such in JLS.
Its high time JLS is debugged!
 
Greenhorn
Posts: 14
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mapraputa Is and srikrish are right.
Note that the code example as originally posted has an incorrect
comment. The following compiles and executes just fine without
any cast:
char charExpression = 0x41;
final byte b = 0x41;
charExpression = b;
whereas if any negative value is used for b, then the
assignment will fail at compile-time with a "possible
loss of precision" error, because char values range from
zero to +2^16-1, and no negative value is representable
in a char. This has nothing to do with the switch statement,
it is a property of assignment-compatibility as defined in
JLS. See the citation given by Mapraputa Is above.
One might indeed wonder why the Java desugners, to use
Mapraputa's delightfully appropriate spelling, did not
also allow the analogous case of narrowing conversions of
floating point values where no loss of precision is entailed
and the value is constant, e.g.
float f = 2.3;
But note that they didn't allow it for long integers either.
For example, this fails at compile time with an error about
possible loss of precision:
final long foobar = 100L;
int blivet = foobar;
So they only allowed this kind of automatic conversion "from
int's down", for whatever reason.
 
michael huang
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
char charExpression = 0x41;
final byte b = 0x41;
charExpression = b;
this code can produce compile error in my computer
and byte b= 0x41 is it negative?
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Jim Goodwin:
Desugners weren�t intented� My apologies to the whole Java design team and to each Java desIgner in particular .
(Excluding those whose last name occupies less than 8 bytes or starts from, say, M letter� )
BTW:
char charExpression = 0x41;
final byte b = 0x41;
charExpression = b;
as michael huang said does produce compile error.
I read JLS again:
<�>
* The expression is a constant expression of type int.
* The type of the variable is byte, short, or char.
<�>
My experiments showed that
charExpression = b;
compiles OK ONLY if b is declared as INT.
 
michael huang
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hi, Mapraputa
does your JLS is 1.0
on JLS 2.0, they say like this:
The expression is a constant expression of type byte, short, char or int.
and i also test
char charExpression = 0x41;
final int b = 0x41;
charExpression = b;
is OK.
my jdk is 1.2.2, is their jdk1.2.2 corresponding to JLS 1.0?
and their JLS2.0 corresponding to JDK 9.9

michael

[This message has been edited by michael huang (edited September 19, 2000).]
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Michael!
What is URL for JLS 2.0?
In source codes for jdk 1.2.2 they give URL which I use: http://java.sun.com/docs/books/jls/html/
 
thomas
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
JLS first edition says that during assignment a narrowing primitive conversion is allowed provided:
  • The expression is a constant expression of type int.

  • The type of the variable is byte, short, or char.

  • The value of the expression (which is known at compile time, because it is a constant expression) is representable in the type of the variable.

  • In JLS second edition, the first condition is amended to read:
    • The expression is a constant expression of type byte, short, char or int.

    • So a compiler based on JLS 1st ed. should scream at both the assignment and the switch, and a compiler based on JLS 2nd ed. should have no problem with either.
      My JDK 1.2 compiler screams at the assignment (when cast is omitted) but passes the switch!
      Now Jim, you said the assignment without a cast compiled OK. So presumably you are using a more recent compiler and this confusion does not exist. Is that right? Are you using JDK 1.3?
      How about Michael and Mapraputa?


      [This message has been edited by thomas (edited September 20, 2000).]
 
michael huang
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mapraputa
JLS2: http://java.sun.com/docs/books/jls/index.html
i donot know if there some place we have wrong understanding about this thing, can moderator explain it?
michael
 
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Guys,
My opinion about some of the issues are as follows:
1) Thomas: Regarding your first post, you ask:
"This code compiles and runs without a hitch eventhough values of type byte CANNOT be assigned to variables of type char without an explicit"
- Please remember that the expression within a switch(expr) must be a byte, short, char or int.
- Next, the values for all the case labels MUST BE COMPILE TIME CONSTANTS.
Upto this point, I hope, everybody agrees.
Next, please note that
- the case constant expr must be assignable to that switch expr.
At this point Thomas asks, why doesn't he get a compiler error?
Well the answer is:
When we have a compile time constant expr that could be REPRESENTED AS A byte, short, char or int being assigned to a variable of type byte, short or char(obviously we don't need an int here !) then an implicit narrowing coversion is done here automatically.
Fine...., lets look at some examples:
byte b = 100; // compile time constant and can be narrowed down //to a byte
int i = 50; // compile time constant
byte b1 = 300; // compiler error ! coz 300 is out of range and //cannot be represented in a byte variable.
consider,
byte b = 100;
final int i = 10;
final int j = 20;
b = i+ j + 10; // Here you have an autamatic narrowing coversion as the expr i + j + 10 is compile time const.
The same thing applies to the switch-case expressions.
Assume that we have byte b;
When we say
switch(b)
{
case 100:
case some value or expression
case 300:
----
-----
}
then the compiler checks if it can assign each case label constants to the byte variable b.
i.e b = 100; // ok
b = 300; // OOOps out of range - compiler error!
Therfore, in Thomas's case code below,
switch (charExpression) {
default:
System.out.println("default");
break;
case b:
}
an implicit narrowing conversion is automatically done as:
i.e. charExpression = 0x41; //same as line final byte b = 0x41;
That's the reason u don't get compiler error. But had you put a negative value as srikish did, the compiler immediately screams coz a char variable can't have -ve values.
(2) Explict Cast:
For all other regular expression(typically non compile time constant expressions), you need an explicit cast if you are performing a narrowing conversion.
short s = 100;
char c = 50;
c = s; // compiler error
s = c; // compiler error
Also, you can see that values in the variables in s & c can be changed at run-time(eg i/p from user for these values).
So, the compiler will have no idea about these run time values and cannot possibly check its validity before assigning. SO, java insists that you put an explict case assuming that the programmer knows what he is doing.

(3) Mapraputa, you are wondering why float f = 2.3 gives a compiler error!
Well, we all know that all floating point literals are automatically assumed as to be double values unless suffixed by an 'F' or 'f'.
I really can't give an accurate answer, all I can tell you is that representing floating point values as a double
is basicaly done for efficient manuplation of the values. (I remember vaguely reading this somewhere)
Since, compiler assumes 2.3 to be a double and therefore assigning to a float means loss of precision. So, the compiler screams!
(4)michael huang, I don't get any error for the code you have given.
Plus 0x41 = 65 in decimal.
Hope this helps
-sampaths77
 
thomas
Ranch Hand
Posts: 79
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sampath:
The point is that the code below does NOT compile with JDK 1.2
<pre>
char charExpression;
final byte b = 0x41;
charExpression = b;
</pre>
The compiler says that an explicit cast is neeed on the third line. Now, could you compile this OK? If you are using JDK, what version are you using?

[This message has been edited by thomas (edited September 20, 2000).]
[This message has been edited by thomas (edited September 20, 2000).]
 
Mapraputa Is
Leverager of our synergies
Posts: 10065
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi everybody!
I tried this program:

And now I�ve got a question:
1. URL for JLS second edition is: http://java.sun.com/docs/books/jls/second_edition/html/jTOC.doc.html
2. I�ve seen even moderators in this forum pointing to �old� URL http://java.sun.com/docs/books/jls/html/
Which version is relevant to the exam? (My compiler said �the first��)
To everybody:
I am not wondering why float f = 2.3 gives a compiler error, I know that 2.3 is double by default and conversion from double to float is considered narrowing. I am wondering why Java designers did not allow automatic narrowing
conversion for double literals whose values are known in compilation phase, like they did for int primitives:
short s = 2; // is OK, inspite 2 is int
float f = 2.3; // is not OK
 
Anonymous
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Mapraputa,
your code compiles fine on my PC.
I have jdk 1.3 under win NT.
-sampaths77
 
michael huang
Ranch Hand
Posts: 63
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
yes, i may be the version of compiler,
i decide to download a jdk1.3 to see if it's the reason.
and can more people use 1.3 test this code to show it.
so how we use JLS?.? to pass the exam.
michael
 
pie. tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
reply
    Bookmark Topic Watch Topic
  • New Topic