aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes Switch statement/case restrictions Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "Switch statement/case restrictions" Watch "Switch statement/case restrictions" New topic
Author

Switch statement/case restrictions

Maduranga Liyanage
Ranch Hand

Joined: May 25, 2005
Posts: 124
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

Joined: May 25, 2005
Posts: 124
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

Joined: Feb 17, 2009
Posts: 40
My compiler says that lines 1, 3 and 4 must be removed.


[Blog] [SCJP6 75%] [SCBCD]
Maduranga Liyanage
Ranch Hand

Joined: May 25, 2005
Posts: 124
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

Joined: Jul 23, 2008
Posts: 352
Switch arguments must be "compatible" with an int, and now as of Java 5, enum values may also be passed.


be a well encapsulated person, don't expose your privates, unless you public void getWife()!
Balu Sadhasivam
Ranch Hand

Joined: Jan 01, 2009
Posts: 874

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

Joined: May 25, 2005
Posts: 124
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

Joined: Jan 01, 2009
Posts: 874



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

Joined: Dec 16, 2008
Posts: 1032
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.


All code in my posts, unless a source is explicitly mentioned, is my own.
Maduranga Liyanage
Ranch Hand

Joined: May 25, 2005
Posts: 124
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

Joined: Feb 04, 2009
Posts: 40
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


SCJP 1.6
SCWCD 1.5 (Preparing...)
Maduranga Liyanage
Ranch Hand

Joined: May 25, 2005
Posts: 124
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

Joined: Feb 04, 2009
Posts: 40
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

Joined: Aug 29, 2008
Posts: 580

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.


SCJP 6
Why to worry about things in which we dont have control, Why to worry about things in which we have control ! !
Abhay Agarwal
Ranch Hand

Joined: Feb 29, 2008
Posts: 1106
    
    1

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


Oracle Java Web Service Developer (1z0-897), Oracle certified Java 7 Programmer, SCJA 1.0, SCJP 5.0, SCWCD 5.0, Oracle SQL Fundamentals I
Cristian Senchiu
Ranch Hand

Joined: Feb 08, 2009
Posts: 40
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

Joined: Dec 16, 2008
Posts: 1032
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.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Switch statement/case restrictions