Trouble with switch statements? - java

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.

Related

Switch : Input remained in console (I've asked this questions several times but no one seems to know why)

Please let me describe the problem verbally first.
What you see on the console is what the problem is.
The coding is done with Scanner and switch-statement.
It asks to User, to who do you want to give MP portion. (each character's MP max is 30)
I wanted to test and tried 2,3,2,4 inputs to see what it would say, and as you could see, it says, "Jongwoo's MP is full. Choose different Character.." and so does for all other characters as expected, except for Kyungseok, who's MP is currently 15. So when I input 1 (for Kyungseok) it says Kyungseok's MP is healed , and all of sudden the rest character does the same thing. (please ignore the amount of it healed, I need to fix that)
One thing I realized was that they were printed in the order that I put in numbers to test : 2, 3, 2, 4.
So the input remained in the console became input and the switch-statement takes it as an input.
I don't know why it does that.
I have a lot of switch-statements, and it is not the only switch-statement having this problem. and the following code is the code for the switch-statement.
public static void chooseMMCha1(Character member) {
boolean wrongAnswer;
do {
wrongAnswer = false;
Scanner sc = new Scanner(System.in);
while(!sc.hasNextInt()) {
sc.next();
}
switch (sc.nextInt()) {
case 1:
chooseMMCha(chosenMember[0], member);
break;
case 2:
chooseMMCha(chosenMember[1], member);
break;
case 3:
chooseMMCha(chosenMember[2], member);
break;
case 4:
chooseMMCha(chosenMember[3], member);
break;
case 5:
chooseMMCha(chosenMember[4], member);
break;
case 6:
turn(member);
break;
default:
System.out.println("From 1 to 6");
wrongAnswer = true;
break;
}
}while(wrongAnswer);
}
It appears what you have here is unintended recursion.
In your chooseMMCha1() method you call chooseMMCha().
This method then checks to see if the selection is valid. If it isn't then it calls chooseMMCha1() again.
However once you input a valid input the call to chooseMMCha1() will come off the stack and it will return to your call to chooseMMCha(). Once it returns to here you print out that the character was healed. Thus once you input a valid input, all the invalid inputs that you pushed onto the stack will resolve and your method will print out that they have been healed.
In the case of an invalid input you need to put a return; statement after your call to chooseMMCha1() to make sure that you don't continue with the method once the invalid inputs come off the stack:
if(chosenMember.getMP() == chosenMember.getMaxMP()) {
System.out.println(chosenMember +"'s MP is already full");
chooseMMCha1(member);
return; //Exit the method
}

Is there some way to call a class which is defined by String or a similar way?

I have a program where, if the user enters "1" then the "Assignment01" class will be called and if the user enters "14" then the "Assignment14" class will be called and so on.
Currently, I am using Switch Case Statement to call a function according to the user's number input like shown on the code. But what if there were 100 of classes which needs to be called per the user's input?
It will be really frustrating to have to create a case for calling every single class. So, is there another way to make it short and efficient?
For example:
// Assume user inputs "10" so 'userInput = 10'
String classVariable = "Assignment" + userInput + ".main(args)";
classVariable; // Result in like 'Assignment10.main(args);'
Unfortunately, this can't be done as that is a String but is there a similar way like to define that String into a class so it can be called like that?
EDIT: All I want is that when the user enters integer like say "30" then the class "Assignment30" should be called which can be done like "Assignment30.main(args);" through a switch case statement but I can't create every single case.
It would be better if I could put like say "Assignment+userInput+.main(args);" or something.
CODE:-
switch (userInput)
{
default:
AssignmentMain.errorLevel();
break;
case 1:
System.out.println();
Assignment01.main(args);
break;
case 2:
System.out.println();
Assignment02.main(args);
break;
case 3:
System.out.println();
Assignment03.main(args);
break;
case 4:
System.out.println();
Assignment04.main(args);
break;
case 5:
System.out.println();
Assignment05.main(args);
break;
}

Is a switch executing all the cases without stopping?

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.

Case insensitive matching in Java switch-case statement

I was wondering if there is a way to perform case insensitive match in java switch case statement. the default implementation is case sensitive. Please see the example below.
public class SwitchCaseTest {
/**
* #param args
*/
public static void main(String[] args) {
switch ("UPPER") {
case "upper" :
System.out.println("true");
break;
default:
System.out.println("false");
break;
}
}
}
So above statement returns false as output. And i am trying make it work for case-insensitive match like String.equalsIgnoreCase() would do. I tried to convert both the string literal to lower case and then compare. but was unable to do so.
If you want to do that: just make sure the input data is in all lowercase, and use lowercase cases...
switch ("UPPER".toLowerCase()) {
case "upper" :
....
Localization issues
Also, the ages old issue of localization strikes again, and plagues this thing too... For example, in the Turkish Locale, the uppercase counterpart of i is not I, but İ... And in return, the I is not transformed to i, but a "dotless i": ı. Don't underestimate this, it can be a deadly mistake...
You try making everything uppercase or lowercase
String str = "something".toUpperCase();
switch(str){
case "UPPER":
}
or
String str = "something".toLowerCase();
swtich(str){
case "lower":
}
or even better use enum (note this is only possible from Java 7)
enum YourCases {UPPER1, UPPER2} // cases.
YourCases c = YourCases.UPPER1; // you will probably get this value from somewhere
switch(c){
case YourCases.UPPER1: ....
break;
case YourCases.UPPER2: ....
}
When using a switch statement you must use "break;" for it to exit the statement, so simply use two cases, one without a break.
switch(choice)
{
case 'I':
case 'i':
//Insert a name
System.out.print("Insert a name to add to the list: ");
input.nextLine();
name = input.nextLine();
nameList.insert(name);
System.out.println();
break;
This way, if either "I" or "i" are entered, both cases will have the same outcome.
try
switch ("UPPER".toUpperCase()) {
case "UPPER" :
To avoid having to use the case expression to verify if it is lowercase or uppercase, I recommend that you use the following:
String value = String.valueOf(userChoice).toUpperCase();
This helps to make the conversion of lowercase to uppercase before doing the evaluation in the switch case.

Jumper in Java?

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

Categories

Resources