File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Switch statement/case restrictions

 
Maduranga Liyanage
Ranch Hand
Posts: 124
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry to bother with another question guys but have a confusion with the Switch/Case.

I was under the impression that the switch statement must be a value that can be assigned to an int. So are for the case statements.
I thought all the case statements and the switch statement will be promoted to int in the compilation.

But after doing an example, I have some problems:
In the following code:

public class SwitchTest {

public static void main(String[] args)
{

final byte x = 2;
final int a = 129;
final byte b = 10;
final byte c = 2;

switch(x){
case a:System.out.println("x=1");
case b:System.out.println("x=10");break;
case c:System.out.println("x=2");
}
}
}


I get the following error:
SwitchTest.java:12: possible loss of precision
found : int
required: byte
case a:System.out.println("x=1");
^
1 error


If I reduce 129 to 127 it compiles fine.

So what I gather from this is, when the switch statement is 'byte', the case statements need to be bytes too, or alteast be able to fit in a byte?
Is that true?
 
Maduranga Liyanage
Ranch Hand
Posts: 124
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I also found this in the Inquisition.

static public void main(String...arg)
{
Byte snake = 5;
final int b;
b=2;
Integer i=5;
switch(snake){
case 128:System.out.println("Shouldn't it freeze in December ?");//1
default:System.out.println("White Christmas?");//2
case b:System.out.println("An Inconvenient truth...");//3
case i:break;//4
}
}


And the explanation says that line 4 (//4) must be removed because "cannot convert an Integer to a Byte".
But I think even 'snake' was an int, this will not work because the case statement needs a constant value, and the compiler errored me saying "constant expression required".
Now my problem is, wrapper classes are immutable. So the int value they are holding is constant. So is this a problem of autoboxing?
 
Angelika Angley
Ranch Hand
Posts: 40
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My compiler says that lines 1, 3 and 4 must be removed.
 
Maduranga Liyanage
Ranch Hand
Posts: 124
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
angelika ann wrote:My compiler says that lines 1, 3 and 4 must be removed.


Yes. That is correct.
My problem is why 128 is an error when it can be put into an int.
Also whether unboxing doesnt work in like 4.

Cheers.
 
Stephen Davies
Ranch Hand
Posts: 352
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Switch arguments must be "compatible" with an int, and now as of Java 5, enum values may also be passed.
 
Balu Sadhasivam
Ranch Hand
Posts: 874
Android Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maduranga Liyanage wrote:
angelika ann wrote:My compiler says that lines 1, 3 and 4 must be removed.


Yes. That is correct.
My problem is why 128 is an error when it can be put into an int.
Also whether unboxing doesnt work in like 4.

Cheers.



signed byte ranges from -128 to 127 !! 128 is out of range.
 
Maduranga Liyanage
Ranch Hand
Posts: 124
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you all.

But my question is still there.

What I want to know is, if my switch statement is a byte, does all my case statements need to be bytes too? or be able to assigned to a byte (without losing precision)?

 
Balu Sadhasivam
Ranch Hand
Posts: 874
Android Java VI Editor
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


What I want to know is, if my switch statement is a byte, does all my case statements need to be bytes too? or be able to assigned to a byte (without losing precision)?


Its neccesary for switch statement to be compatible of "int". Considering byte passed as case statement it holds good " as long it can be assigned to a byte (without losing precision)"
 
Ruben Soto
Ranch Hand
Posts: 1032
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When in doubt, the JLS is a good source. This is from the JLS, 14.1:


• Every case constant expression associated with a switch statement must be
assignable (§5.2) to the type of the switch Expression.

• No switch label is null.
• No two of the case constant expressions associated with a switch statement
may have the same value.
• At most one default label may be associated with the same switch state-
ment.


It makes perfect sense this is enforced, because if it weren't, that particular switch case would never get executed, as a byte can never evaluate to 129. The compiler catches this.
 
Maduranga Liyanage
Ranch Hand
Posts: 124
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you very much Balu and Ruben.
So if I use either of char, byte, short or int in a switch, I must the same type in my case statements too (atleast be able to assign it to that particular type).. plus the switch statement (only) needs to be assignment compatible to int (not the case staements, but that is implicitly implied).


Cheers guys.
 
Samrat Som
Ranch Hand
Posts: 40
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Ruben for making us realize, that JLS comes to the picture when in a jinx about the specification.

Maduranga
plus the switch statement (only) needs to be assignment compatible to int (not the case staements


You cant say this rather going through the specification in JLS , this is the appropriate of saying it
The type of the Expression must be char, byte, short, int, Character, Byte, Short, Integer, or an enum type (§8.9), or a compile-time error occurs.


Correct me if I am wrong
 
Maduranga Liyanage
Ranch Hand
Posts: 124
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank you Samrat.
But its confusing why I cannot get Integer to work despite being mentioned in the specification

import java.lang.*;
public class SwitchTest {

public static void main(String[] args)
{

final int x = 2;
final int a = 127;
final byte b = 10;
final Integer IntObj = new Integer(2);

switch(x){
case a:System.out.println("x=1"); break;
case b:System.out.println("x=10");break;
case IntObj:System.out.println("x=2"); break;
}
}
}


And I get:
SwitchTest.java:16: constant expression required
case IntObj:System.out.println("x=2"); break;



Cheers
 
Samrat Som
Ranch Hand
Posts: 40
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I understand your concern , But You can see one thing in the specification :
Every case constant expression associated with a switch statement must be
assignable (§5.2) to the type of the switch Expression.


The case has to be compile time constant expression .And according to the JLS
A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

Literals of primitive type and literals of type String (§3.10.5)
Casts to primitive types and casts to type String
The unary operators +, -, ~, and ! (but not ++ or --)
The multiplicative operators *, /, and %
The additive operators + and -
The shift operators <<, >>, and >>>
The relational operators <, <=, >, and >= (but not instanceof)
The equality operators == and !=
The bitwise and logical operators &, ^, and |
The conditional-and operator && and the conditional-or operator ||
The ternary conditional operator ? :
Parenthesized expressions whose contained expression is a constant expression.
Simple names that refer to constant variables (§4.12.4).
Qualified names of the form TypeName . Identifier that refer to constant variables (§4.12.4).


It has to be of primitive types, whereas IntObj is object reference tyep. You can use this reference in the Expression of switch as mentioned , but in Case statements . The variable needs to be constant type expression.

 
James Tharakan
Ranch Hand
Posts: 580
Eclipse IDE
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maduranga Liyanage wrote: But its confusing why I cannot get Integer to work despite being mentioned in the specification


Look at Henry Wong's post.
 
Abhay Agarwal
Ranch Hand
Posts: 1375
Eclipse IDE Java
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
import java.lang.*;
public class SwitchTest {

public static void main(String[] args)
{

final int x = 2;
final int a = 127;
final byte b = 10;
final Integer IntObj = new Integer(2);

switch(x){
case a:System.out.println("x=1"); break;
case b:System.out.println("x=10");break;
case IntObj:System.out.println("x=2"); break;
}
}
}

Reason for getting " SwitchTest.java:16: constant expression required
case IntObj:System.out.println("x=2"); break; " error is because

line -- final Integer IntObj = new Integer(2); says that IntObj is final reference but its value can change. That's why it is giving error as 'constant expression required ' at compile time
 
Cristian Senchiu
Ranch Hand
Posts: 40
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Abhay Agarwal wrote:
line -- final Integer IntObj = new Integer(2); says that IntObj is final reference but its value can change.


Make no mistake: wrappers are immutable ...
So after that line above, IntObj is written in stone.
 
Ruben Soto
Ranch Hand
Posts: 1032
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's right. Technically, it would be possible to use a final Integer reference in a case expression, but the specification doesn't allow it, because a final Integer reference, although unchangable for all intents and purposes (the object it points to is immutable, and the reference can't be reassigned to point to a different object,) is not considered a compile-time constant. In other words, the compiler doesn't consider those as constants as it is parsing your code.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic