I'm on Java 8v60. I tried to embed a switch regarding an exception group in a catch block. Apparently, the case are recognised, but once they get into the switch, they keep going through all the possible cases. Is this a Java bug?
It looks like this:
try {
...
} catch (DateTimeParseException exc) {
...
} catch (myException exc) {
switch (exc.getEvent()) {
case EVENT_ONE :
//once EVENT_ONE gets here;
case EVENT_TWO : case EVENT_THREE :
//it keeps going everywhere;
case EVENT_FOUR :
//and so on;
default :
//and here of course too.
//but if it's not one of the above, it just appears here only
}
...
Weird, isn't it. Any idea?
No. It's not a bug. You are not implemented switch properly. It's fall through. You need to have break after each case.
For ex :
switch (exc.getEvent()) {
case EVENT_ONE :
//once EVENT_ONE gets here;
break;
case EVENT_TWO : case EVENT_THREE :
//it keeps going everywhere;
break;
case EVENT_FOUR :
//and so on;
break;
Here is the official doc for the same
Another point of interest is the break statement. Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, statements in switch blocks fall through: All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered.
The switch statements jump to the right value, and continue up to the end of other cases.
If you like to exit the switch statement you have to use a break (or return in some situations).
This is useful to handle situations in wich many values can be handled at the same manner:
switch (x) {
case 0:
case 1:
case 2:
System.out.println("X is smaller than 3");
break;
case 3:
System.out.println("X is 3");
case 4:
System.out.println("X is 3 or 4");
break;
}
If the case selection is also a final condition for a method you can return from it.
public String checkX(int x) {
switch (x) {
case 0:
case 1:
case 2:
return "X is smaller than 3";
case 3:
return "X is 3";
case 4:
return ("X is necessary 4");
default:
return null;
}
}
}
Its not java bug. It's your logical bug.
put break statement after each case statement to avoid fall through situation.
Related
I am just trying to write a program that generates a random year between 2000 and 2010, then reads off a space exploration fact that occurred in that year.
This is the code that I have written, however when I run it, no matter what year is generated, it just prints the last case (2010). How do I fix this?
import java.util.Random;
public class SpaceExploration {
public static void main(String[] args) {
int year =(int)(Math.random()*11) + 2000;
String eventString = "";
switch (year) {
case 2000: eventString = "2000: First spacecraft orbits an asteroid";
case 2001: eventString = "2001: First spacecraft lands on asteroid";
case 2002: eventString = "2002: N/A";
case 2003: eventString = "2003: Largest infrared telescope released";
case 2004: eventString = "2004: N/A";
case 2005: eventString = "2005: Spacecraft collies with comet";
case 2006: eventString = "2006: Spacecraft returns with collections from a comet";
case 2007: eventString = "2007: N/A";
case 2008: eventString = "2008: Kepler launched to study deep space";
case 2009: eventString = "2009: N/A";
case 2010: eventString = "2010: SpaceX sucessfully sends spacecraft to orbit and back";
}
System.out.println(eventString);
}
}
You need to add break statement after each case else after finding matching case it will just execute all cases until it finds break or the end which in your case is 2010.
Your code should look like:
switch (year) {
case 2000:
eventString = "2000: First spacecraft orbits an asteroid";
break;
case 2001:
eventString = "2001: First spacecraft lands on asteroid";
break;
...
notice the break after every case.
The other answers are correct, you have to introduce the break after every case.
In general you should also add the case default case and add some console output to make sure you're software is working as intended.
An alternative solution would be to use a HashMap:
Map<Integer, String> map = new HashMap<>();
map.put(2010, 2010: SpaceX sucessfully sends spacecraft to orbit and back);
...
String eventString = map.get(year);
Like this, you would enter the switch statement at the year you're providing and then fall-through all the way to the last case. That way, your eventString always contains the value of year 2010. To prevent this, simply add a break statement in each case.
Break is the keyword which is use to jump from the loop (while,do-while and for) and switch statements, break should be use when certain conditions matches and you want to come out from the loops or switch.
while(true){
if(true) {
break ; // when you want to get out from the loop
}
}
and for switch statements you should use break statements to get out from the loop.
What you have experienced is a feature of the switch statement called 'fall through'.
Although usually one uses the break variant (which makes sense in most cases) there are some applications to be executed in a defined order, falling through some cases in a waterfally manner. Look at the application below(link):
Another point of interest is the break statement. Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, statements in switch blocks fall through: All statements after the matching case label are executed in sequence, regardless of the expression of subsequent case labels, until a break statement is encountered. The program SwitchDemoFallThrough shows statements in a switch block that fall through. The program displays the month corresponding to the integer month and the months that follow in the year:
public class SwitchDemoFallThrough {
public static void main(String[] args) {
java.util.ArrayList<String> futureMonths =
new java.util.ArrayList<String>();
int month = 8;
switch (month) {
case 1: futureMonths.add("January");
case 2: futureMonths.add("February");
case 3: futureMonths.add("March");
case 4: futureMonths.add("April");
case 5: futureMonths.add("May");
case 6: futureMonths.add("June");
case 7: futureMonths.add("July");
case 8: futureMonths.add("August");
case 9: futureMonths.add("September");
case 10: futureMonths.add("October");
case 11: futureMonths.add("November");
case 12: futureMonths.add("December");
break;
default: break;
}
if (futureMonths.isEmpty()) {
System.out.println("Invalid month number");
} else {
for (String monthName : futureMonths) {
System.out.println(monthName);
}
}
}
}
So if you want to get all space exploration facts that occurred in that year and later, you can omitt the breaks.
My code looks like:
switch(read.nextInt()){
case 1:
//do "a" and print the result
break;
case 2:
//do "b" and print the result
break;
case 3:
//do "a" and print the result
//do "b" and print the result
}
Is there another way to do it without simply copying what's inside case 1 and 2?
I just started my graduation, so I can only use String and Scanner for this, thanks :)
Define two methods called doA() and doB() and call them. This way you won't duplicate your code. Also are you sure you don't need break statements after each case statement?
switch(read.nextInt()){
case 1:
doA();
break;
case 2:
doB();
break;
case 3:
doA();
doB();
break;
default:
// do something
break;
}
A tricky one, IMO more readable:
int nextInt = read.nextInt();
if (nextInt % 2 == 1) { // or if (nextInt == 1 || nextInt == 3) {
// do "a" and print the result
}
if (nextInt > 1) {
// do "b" and print the result
}
In cases like this it probably makes sense to create methods for
//do "a" and print the result
and
//do "b" and print the result
In case 3 you would just call these methods one after the other.
Looks like you've forgot about 'break'. It makes code "break" from switch statement. If you want in case of '1' & '2' do the same thing and in case of '3' the other thing, you can write:
switch(read.nextInt()){
case 1:
case 2:
//do "a" or "b" and print the result
break; //break from switch statement, otherwise, the code below (yes, I mean "case 3") will be executed too
case 3:
//do "a" and print the result
//do "b" and print the result
}
It is a usual thing to add "break" in the end of "case" block if you don't want the same code block to be executed for several values:
switch(n){
case 1:
//do something
break;
case 2:
//do other things
break;
case 3:
//more things!
//you may not write "break" in the last "case" if you want
}
switch (i) {
case ("+" || "/"):
setOperator("i");
break;
}
What is the best way to do this in Java?
Of course.
Just use
if(i.equals("+") || i.equals("/")) {
setOperator("i");
}
OR if you have to use a switch statement, you can do it this way:
switch(i) {
case "+":
case "/":
setOperator("i");
break;
}
Basically, you can't really have multiple cases the way you had thought about it. It's not the same structure as an if statement, where you can do various logical operations. Java does not go through and do an if statement for each of the cases.
Instead, each time you have case("foo"), Java sees this as something called a Case Label. It is the reason that we sometimes opt to use switch statements, even though they are very primitive and sometimes not very convenient. Because we have case labels, the computer only has to do one evaluation, and it can jump to correct place and execute the right code.
Here is a quote from a website that may help you:
A switch statement, as it is most often used, has the form:
switch (expression) {
case constant-1:
statements-1
break;
case constant-2:
statements-2
break;
.
. // (more cases)
.
case constant-N:
statements-N
break;
default: // optional default case
statements-(N+1)
} // end of switch statement
This has exactly the same effect as the following multiway if statement, but the switch statement can be more efficient because the computer can evaluate one expression and jump directly to the correct case, whereas in the if statement, the computer must evaluate up to N expressions before it knows which set of statements to execute:
if (expression == constant-1) { // but use .equals for String!!
statements-2
}
else if (expression == constant-2) {
statements-3
}
else
.
.
.
else if (expression == constant-N) {
statements-N
}
else {
statements-(N+1)
}
switch (i) {
case ("+"):
case ("/"):
setOperator("i");
break;
}
yes you can do as: Fall through in swith case
switch (i) {
case "+":
case "/":
setOperator(i);
break;
}
Is there any syntax that allows you to jump from one line to the other?
example:
System.out.println("line");
System.out.println("line2");
System.out.println("line3");
System.out.println("line4");
//goto line2 or something like that??
No, there is no goto statement, but there are several workarounds:
do {
//do stuff
if (condition) break; //this will jump--+
//do stuff // |
} while (false); // |
// here <-----------------------------------+
and
int id = 0;
while (true) {
switch (id) {
case 0:
//do stuff
if (condition) {id = 3; break;} //jumps to case 3:
case 1:
if (condition) {id = 1; break;} //jumps to case 1:
// ...
}
}
You can achieve this in a roundabout way, for example with a switch statement:
switch (lineNum) {
case 1: System.out.println("line 1");
case 2: System.out.println("line 2");
case 3: System.out.println("line 3");
case 4: System.out.println("line 4");
}
Now you must ensure lineNum has the appropriate value.
For any backward jumps you'll need a do or while loop.
Java intentionally does not support goto. This is to encourage (force) you to build the control flow using the proper conditional constructs.
In your example, the proper method would be a while-loop:
System.out.println("line");
while (true) {
System.out.println("line2");
System.out.println("line3");
System.out.println("line4");
}
If you think about it, there is no code flow pattern that cannot be expressed without the need for goto (it may require to stray from personal ingrained habits). The only time you may want to use goto is to avoid code duplication. If you encounter such a case, restructuring the code into a separate method that can be called where needed is a much cleaner solution.
There is no goto in Java although it is a reserved keyword.
A goto is considered a bad programming construct and, as such, was left out of Java.
what exactly do you want to achieve? you could use labels as in http://geekycoder.wordpress.com/2008/06/25/tipjava-using-block-label-as-goto/, anyway using goto like statements could lead to spaghetti code
In the 1 month experience I've had with any programming language, I've assumed that switch case conditions would accept anything in the parenthesis as a boolean checking thingamajig, ie
these:
|| && < >
Know what I mean?
something like
char someChar = 'w';
switch (someChar) {
case ('W' ||'w'):
System.out.println ("W or w");
}
Sadly, doesn't seem to work that way. I can't have boolean checking in switch case.
Is there a way around it?
By the way, terribly sorry if I'm sounding confusing. I don't quite know the names for everything in this language yet :X
Any answers appreciated
You can achieve an OR for cases like this:
switch (someChsr) {
case 'w':
case 'W':
// some code for 'w' or 'W'
break;
case 'x': // etc
}
Cases are like a "goto" and multiple gotos can share the same line to start execution.
You can do -
switch(c) {
case 'W':
case 'w': //your code which will satisfy both cases
break;
// ....
}
Every case is normally followed by a "break;" statement to indicate where execution should terminate. If you omit the "break;", then execution will continue. You can use this to support multiple cases which should be handled the same way:
char someChar = 'w';
{
case 'W':
// no break here
case 'w':
System.out.println ("W or w");
break;
}
Switch cases are branches for alternative evaluations of a given expression. The expression is given in the switch parenthesis and can be byte, short, char, and int data types.
The body of a switch statement is known as a switch block. A statement
in the switch block can be labeled with one or more case or default
labels. The switch statement evaluates its expression, then executes
all statements that follow the matching case label.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
For an alternate to switch statement(multiple if conditions), I think the best solution will be using an enum. For example: Consider the case below:-
public enum EnumExample {
OPTION1{
public double execute() {
Log.info(CLASS_NAME, "execute", "The is the first option.");
return void;
}
},
OPTION2{
public double execute() {
Log.info(CLASS_NAME, "execute", "The is the second option.");
return void;
}
},
OPTION3{
public double execute() {
Log.info(CLASS_NAME, "execute", "The is the third option.");
return void;
};
public static final String CLASS_NAME = Indicator.class.getName();
public abstract void execute();
}
The above enum can be used in the following fashion:
EnumExample.OPTION1.execute();
Hopefully this helps you guys.