JAVA: Switch Statement Seems to be Skipping every second Case condition [duplicate] - java

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 2 years ago.
I have been Stumped, I'm using the Eclipse IDE and am building a game using ATW and Swing. however, a random bug snuck its way into my script and I don't know how or why as this part of the code has not been touched in ages. Essentially I am using a switch statement to determine which images are to be loaded at what time to create a sort of intro sequence, Here is the script:
// condition that only runs once within the print function
if (gameState == "start")
{
//gameAudio.loopMusic(false);
//intro animation
switch(startCounter)
{
//3 and a half seconds of buffer split into 10 parts to allow for updating screen during startup of app
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
wait(350);
break;
case 10:
gameAudio.playMusic("src/res/audio/JackEditedIntro.wav");
gameAudio.setVolume(0.6);
wait(300);
samIcon = new ImageIcon("src/res/SamAssets/SamFullBody/SwingUpSam.png");
break;
case 11:
wait(40);
samIcon = new ImageIcon("src/res/SamAssets/SamFullBody/HighFiveSam.png");
samPow = new ImageIcon("src/res/SamAssets/SamFullBody/PowSam.png");
break;
case 12:
wait(100);
samIcon = new ImageIcon("src/res/SamAssets/SamFullBody/HighFiveSam.png");
samPow = new ImageIcon("");
break;
case 13:
wait(1200);
samIcon = new ImageIcon("src/res/SamAssets/SamFullBody/WaveSam.png");
break;
case 14:
wait(1200);
samIcon = new ImageIcon("src/res/SamAssets/SamFullBody/SwingUpSam.png");
break;
case 15:
wait(40);
samIcon = new ImageIcon("src/res/SamAssets/SamFullBody/IdleSam.png");
break;
case 16:
wait(500);
samIcon = new ImageIcon("");
break;
case 17:
wait(300);
gameAudio.playMusic("src/res/audio/BattleStart.wav");
wait(2000);
break;
default:
wait(5);
System.out.println("Default start up switch statement");
}
setBackground(Color.BLACK);
samIcon.paintIcon(this, g, 540, 20);
samPow.paintIcon(this, g, 720, 20);
//samIcon.ImageIcon();
if (startCounter < 17)
{
startCounter += 1;
}
else
{
//start the actual game
gameState = "menu";
//play the song
gameAudio.playMusic("src/res/audio/AllTheWay.wav");
gameAudio.setVolume(0.2);
gameAudio.loopMusic(true);
// default Sam
samIcon = new ImageIcon("src/res/SamAssets/IdleSam.png");
}
}
The Issue is that not all of my images are being loaded and some sound files are not playing (I quintuple checked the source files which, again, have not been touched for ages and should not be part of the problem). The script appears to be skipping case 11, case 13, case 15 and case 17 so my best guess would be that the script is skipping every second case condition (hard for me to verify if it is skipping in the earlier parts of the statement), but i haven't the faintest as to why. If anyone could shine some light on my issue I would greatly appreciate it.
PS: This is only my second huge coding project in my entire life and so I deeply apologize for the damningly terrifying coding style and hope you can forgive me, thank you.
Update: I added a System.out.println to every case incrementation and every number is appearing in the console despite the images and audio not being loaded in those same cases. Consider me 200% more confused, I desperately need help.

do you stay in a conditional "while" and any moments you variable implements +1,
and i your logic there is a condition that implement +1. Please remove it:
if (startCounter < 17)
{
startCounter += 1;
}
or review this logic, because in any moment do you sum plus 1.

Related

(Java) How do I make switch if one of the case contains <,>,<=, or >= [duplicate]

I want to use the switch statement in some simple code i'm writing.
I'm trying to compare the variable in the parenthesis with values either < 13 or >= 13.
Is this possible using Switch?
var age = prompt("Enter you age");
switch (age) {
case <13:
alert("You must be 13 or older to play");
break;
case >=13:
alert("You are old enough to play");
break;
}
Directly it's not possible but indirectly you can do this
Try like this
switch (true) {
case (age < 13):
alert("You must be 13 or older to play");
break;
case (age >= 13):
alert("You are old enough to play");
break;
}
Here switch will always try to find true value. the case which will return first true it'll switch to that.
Suppose if age is less then 13 that's means that case will have true then it'll switch to that case.
Instead of switch you can easily to the same thing if else right?
if(age<13)
alert("You must be 13 or older to play");
else
alert("You are old enough to play");
This worked in my case:
var enteredAge = prompt("Enter your age");
let ageMoreThan13 = parseInt(enteredAge) >= 13;
let ageLessThan13 = parseInt(enteredAge) < 13;
switch (ageMoreThan13 || ageLessThan13) {
case ageLessThan13:
alert("You must be 13 or older to play");
break;
case ageMoreThan13:
alert("You are old enough to play");
break;
}
Instead of switch use nested if else like this:
if (x > 10) {
disp ('x is greater than 10')
}
else if (x < 10){
disp ('x is less than 10')
}
else
{
disp ('error')
}
You may use a conditional (ternary) operator instead. It takes a condition followed by a question mark (?), then an expression to execute if the condition is true and another if it is false.
This operator is frequently used as a shortcut for the if statement.
age >= 13 ? "You are old enough to play" : "You must be 13 or older to play";
It might be a bit silly to do this with a switch-case, but I added an answer where using switch-case, just for completeness.
var age = prompt("Enter you age");
switch (age) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
alert("You must be 13 or older to play");
break;
default:
alert("You are old enough to play");
break;
}

Syntax for switch-case in Java

I'm using switch case in Java for the first time and I'm a bit unsure about the syntax. Assuming the setTeamName function works, which it does, would the following function make all of the teams in my array have the placeholder String as it's name or should I from case 0: since i starts at 0?
public static Team[] makeTeams(){
Team[] teams = new Team[10];
for(int i = 0; i < teams.length; i++){
switch(i){
case 1: teams[0].setTeamName("Arsenal");
case 2: teams[1].setTeamName("Arsenal");
case 3: teams[2].setTeamName("Arsenal");
case 4: teams[3].setTeamName("Arsenal");
case 5: teams[4].setTeamName("Arsenal");
case 6: teams[5].setTeamName("Arsenal");
case 7: teams[6].setTeamName("Arsenal");
case 8: teams[7].setTeamName("Arsenal");
case 9: teams[8].setTeamName("Arsenal");
case 10: teams[9].setTeamName("Arsenal");
}
}
return teams;
}
use break Statement after every instruction in case.
Your case statements would need to start from 0, because as you rightly observe, i starts at zero. However, this appears to be the least of your problems (unless this is just an exercise in using switch case).
You don't need switch case in this situation at all. Plus, you never create any objects in the array, so every time you attempt to access the array at a particular index, you're going to get a null reference exception. The following will suffice:
Team[] teams = new Team[10];
for (int i = 0; i < teams.length; i++) {
teams[i] = new Team();
teams[i].setTeamName("Arsenal");
}
What you've effectively got in your original example is an example of an anti-pattern, the Loop-switch sequence. If you want the original example to work properly using this anti-pattern (for educational purposes only), you need to add break; statements to ensure that your case statements don't fall through:
Team[] teams = new Team[10];
for (int i = 0; i < teams.length; i++) {
teams[i] = new Team();
switch (i) {
case 0: teams[0].setTeamName("Arsenal"); break;
case 1: teams[1].setTeamName("Arsenal"); break;
case 2: teams[2].setTeamName("Arsenal"); break;
case 3: teams[3].setTeamName("Arsenal"); break;
case 4: teams[4].setTeamName("Arsenal"); break;
case 5: teams[5].setTeamName("Arsenal"); break;
case 6: teams[6].setTeamName("Arsenal"); break;
case 7: teams[7].setTeamName("Arsenal"); break;
case 8: teams[8].setTeamName("Arsenal"); break;
case 9: teams[9].setTeamName("Arsenal"); break;
}
}
Without the breaks, every case statement under the one that matches i is evaluated, e.g. when i == 0, all of the case statements will be executed.
You do have options in filling up the array but if your task requires you to use only switch then start with case 0 instead of 1, since 0 is the "first" case you are encountering.
Do you really need switch here? for loop will be enough.
Switch just move execution to case row and ignore another case for next time. So when you give i = 1 to switch all of the case statement will be executed. You can prevent it by using break;
switch (i) {
case 1:
teams[0].setTeamName("Arsenal");
break;
case 2:
teams[1].setTeamName("Arsenal");
break;
}
You are doing a lot of unnecessary work. Try
public static Team[] makeTeams(){
Team[] teams = new Team[10];
for(int i = 0; i < teams.length; i++){
teams[i] = new Team();
teams[i].setTeamName("Arsenal");
}
return teams;
}
You have few errors in your code:
1) You do not have case 0 - so it is not used. Suggestion is always use default case.
2) Each case should be finished with break; Otherwise all cases below are executed too. For example for case 9 these cases are called 9 and 10. and for case 1 all 10 cases have been called. (but for case 0 in your code none is called).
3) You had reserved array of 10 teams but you did not populated objects to this array. You code will produce null pointer exception.

Show me how `String n = null;` works?

This is my code, and it works exactly how I want it to, but I picked up using
String n = null;
when dealing with switch statements, can someone explain to me why it works the way it does in this code so that I can better understand this concept?
//Tells a user what number corresponds with what numbers on a telephone
import java.util.Scanner;
public class KeyPad
{
public static void main (String [] args)
{
//Initialize Scanner
Scanner input = new Scanner(System.in);
//Variables
String x;
char c;
//Input
System.out.println("Enter a letter: ");
x = input.next();
//Convert to lowercase
x = x.toLowerCase();
c = x.charAt(0);
//Assign reference variable
String n = null;
//Switch conditions
switch (c)
{
case 'a':
case 'b':
case 'c': n = "2";
break;
case 'd':
case 'e':
case 'f': n = "3";
break;
case 'g':
case 'h':
case 'i': n = "4";
break;
case 'j':
case 'k':
case 'l': n = "5";
break;
case 'm':
case 'n':
case 'o': n = "6";
break;
case 'p':
case 'q':
case 'r':
case 's': n = "7";
break;
case 't':
case 'u':
case 'v': n = "8";
break;
case 'w':
case 'x':
case 'y':
case 'z': n = "9";
break;
}
//Output
System.out.println("The corresponding number is " + n);
}
}
This is a question of scope. The Java language considers the entire body of a switch statement as a single scope--it does not try to do in-depth analysis of code paths. For example, the following could spell trouble:
switch(foo){
case 1:
int i = 1;
// note no break
case 2:
int i = 4;
}
This would effectively be a double-declaration. Or, the following could be problematic, and the compiler doesn't analyze it, thus assuming that it would be problematic:
switch(foo){
case 1:
int i = 1;
// note no break
case 2:
i = 4;
}
To handle this, the entire switch block is treated as a single scope. You must declare the variable once in this scope, and you must ensure that all code paths will actually give the variable a value, by immediately initializing it to null. The null value simply indicates the lack of an object, as opposed to String s; which might never get initialized by some otherwise-valid code path.
Well, in order to understand that you have to look after the bytecode of such a class.
In order to clarify I've created a test class as follow:
switch(c){
case 1:
String temp = "first";
System.out.println(temp);
break;
case 2:
temp = "second";
System.out.println(temp);
break;
case 3:
String temp2 = "third";
System.out.println(temp2);
}
Using the javap to generate the bytecode, we get the following LocalVariableTable:
LocalVariableTable:
Start Length Slot Name Signature
0 65 0 args [Ljava/lang/String;
2 63 1 c I
31 10 2 temp Ljava/lang/String;
44 10 2 temp Ljava/lang/String;
57 7 3 temp2 Ljava/lang/String;
What that table of local variables tell us is:
There is a variable of type String named temp which has a valid context from instruction 31 to 41 (31 + 10)
There is a another variable of type String named temp which has a valid context from instruction 44 to 54 (44 + 10)
There is another variable of type String named temp2 which has a valid context from 57 to 64 (57 + 7)
So, the compiler does not treated the whole switch block as one scope, it did created two distinct scopes for the "String temp" variable.
If you try another example, as the source code bellow:
//first scope
{
String myLocal = "first";
System.out.println(myLocal);
}
//second scope
{
String myLocal = "second";
System.out.println(myLocal);
}
The respective bytecode points to the following LocalVariableTable:
LocalVariableTable:
Start Length Slot Name Signature
67 7 2 myLocal Ljava/lang/String;
77 7 2 myLocal Ljava/lang/String;
What shows that two scopes was created for variable myLocal of type String. Exactly the same way it created for the switch statement.
In your case the switch statement just use a LocalVariableTable which has a scope that covers the whole switch statement, that is the main reason you can set a String declared outside the switch. The code bellow illustrate that:
int c = 5;
String temp = null;
switch(c){
case 1:
temp = "first";
System.out.println(temp);
break;
case 2:
temp = "second";
System.out.println(temp);
break;
}
Now, notice the bytecode generate:
LocalVariableTable:
Start Length Slot Name Signature
0 89 0 args [Ljava/lang/String;
2 87 1 c I
4 85 2 temp Ljava/lang/String;
Here you can see the "String temp" variable has a scope of length 85, what covers the whole switch statement, what allows you to reference the variable inside it.
Sorry for the long answer, but such a question is like ask a mathematician to explain what a function means. In order to answer you question is necessary to understand deep concept of how source code works behind the scenes.
Hope this can help, regards.
If I understand the question correctly you are either asking "Why do I set the string n equal to null?" or "Why does my switch statement work correctly?" So I will answer both.
First, You are setting the string to null first to ensure that it is blank, and contains no data( or to a memory location of "0" ). Basically, you are telling the compiler that n is actually nothing at all, it doesn't even exist, except for in its name.
Now, on to the switch statement. You have your standard fall through switch statement. So if the variable c in your snippet is one of the letters "a" "b" or "c" it will then set the string n ( which until this point is still nothing, if you attempt to use it it will throw an error ) and sets it to the string "2"(I assume you know the difference between strings and integers ).
You may be thinking, why does n still exist after the switch statement( or why is it still not null )? This is because of the scope of the variable. Since it was declared inside of main, anything inside of main will be able to see, and change the value of n. now if you did the following
.
.
.
string n = null;
switch(c)
{
case "a":
case "b":
case "c":
string n="2";
break
.
.
.
}
System.out.println("The corresponding number is " + n);
You would get an error, since you re-declared n, in the scope of the switch statement. In this example the n in the switch statement DOES NOT have the same scope as the n being printed. Where as in your example the "case "c": n=2;" n DOES have the same scope( and in fact the same variable ) as the n being printed to the screen.
Also, just a quick fyi, You could also use this method as a check to see that n was in fact set to something before printing it ( and prevent troublesome ArgumentNull exceptions ).
if(n!=null)
System.out.println("The corresponding number is " + n);
else
System.out.println("The character you entered does not have a corresponding number");
I hope this helps clear things up a bit!

If-else working, switch not [duplicate]

This question already has answers here:
In a switch statement, why are all the cases being executed?
(8 answers)
Closed 1 year ago.
I am making an app that has a grid of images with text and each one opens a different activity. It works fine but just for design purposes I want to replace my if-else statements with switch statements (which I assume I can do) however it doesn't work. Right now my working code to set the label on each image is:
if(position == 0)
textView.setText(R.string.zero);
else if(position == 1)
textView.setText(R.string.one);
else if(position == 2)
textView.setText(R.string.two);
else if(position == 3)
textView.setText(R.string.three);
else if(position == 4)
textView.setText(R.string.four);
else if(position == 5)
textView.setText(R.string.five);
ect....
I want to use:
switch(position)
case 0:
textView.setText(R.string.zero);
case 1:
textView.setText(R.string.one);
case 2:
textView.setText(R.string.two);
case 3:
textView.setText(R.string.three);
case 4:
textView.setText(R.string.four);
but when I did that ever label was the last one that I defined (in my example it would be "four"). I also have a similar code for each object to start a different intent with the position variable however that does the opposite and makes every intent equal to the first one. Is my syntax wrong or will this not work for my situation?
You need to break; after each statement in a case, otherwise execution flows down (all cases below the one you want will also get called), so you'll always get the last case.
switch(position) {
case 0:
textView.setText(R.string.zero);
break;
case 1:
textView.setText(R.string.one);
break;
case 2:
textView.setText(R.string.two);
break;
case 3:
textView.setText(R.string.three);
break;
case 4:
textView.setText(R.string.four);
break;
}
Here's the official tutorial explaining when to and when not to use break;.
You need to break; after each branch:
switch (position) {
case 0:
textView.setText(R.string.zero);
break; // <-- here
// etc
}
Legitimate uses of switch when you don't break exist, those are called fall throughs; or because you return or throw.:
switch (someNumber) {
case 0:
return 0;
// no need for break here
case 1:
throw new IllegalArgumentException();
// no need to break here
case 2:
System.out.println("Oh, I got two!");
// fall through
case 3:
return 3;
default:
System.out.println("Meh")
// No need to break: last possible branch
}
return -1;
will return 3 even if you enter 2.
But otherwise you need to break.
Using a break statement after each case should fix the problem. I would also use a default statement as well after the last case.
This is the solution. You need to use break to avoid going through each case:
switch(position)
case 0:
textView.setText(R.string.zero);
break;
case 1:
textView.setText(R.string.one);
break;
case 2:
textView.setText(R.string.two);
break;
case 3:
textView.setText(R.string.three);
break;
case 4:
textView.setText(R.string.four);
break;
I would recommend to read the oracle documentation about the switch statement.
You need to use break statement after eace case operations. In a switch-case statement if you dont use a break statement then all the cases after that specific one will be executed also
case 0:
textView.setText(R.string.zero);
break;
Don't forget to put break; after each case: like that:
switch(position){
case 0:
textView.setText(R.string.zero);
break;
case 1:
textView.setText(R.string.one);
break;
case 2:
textView.setText(R.string.two);
break;
case 3:
textView.setText(R.string.three);
break;
case 4:
textView.setText(R.string.four);
break;
}
In the Switch-case statements, you need to put break; after each case.
switch(position){
case 0:
textView.setText(R.string.zero);
break;
case 1:
textView.setText(R.string.one);
break;
case 2:
textView.setText(R.string.two);
break;
case 3:
textView.setText(R.string.three);
break;
case 4:
textView.setText(R.string.four);
break;
default:
System.out.println("not available");
}
Also you need to put default: at last, because when all case are wrong that time perform default: action.
In the switch-case statement not forgot about break; and default action.
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.
Switch is faster than if-else statement
Bottom line : Default is optional(works like else statement in switch), Break is mandatory.
Interesting fact: you won't see any compilation error, even if you forgot to place the break statement.
The switch needs a break with in each case. But in your case it could be done much simpler by defining an array as shown below.
String values = {R.string.zero, R.string.one, R.string.two, ... };
Use this to populate textView : textView.setText(values[position]);

Java: Can I fall through only one case in a switch statement

In Java, can I fall through only one of the cases in a switch statement? I understand that if I break, I will fall through to the end of the switch statement.
Here's what I mean. Given the following code, on case 2, I want to execute case 2 and case 1. On case 3, I want to execute case 3 and case 1, but not case 2.
switch(option) {
case 3: // code
// skip the next case, not break
case 2: // code
case 1: // code
}
No, what you are after is not possible with a switch statement. You will fall through each case until you hit a break. Perhaps you want case 1 to be outside of your switch statement, so that it is executed regardless.
Put the code into methods and call as appropriate. Following your example:
void case1() {
// Whatever case 1 does
}
void case2() {
// Whatever case 2 does
}
void case3() {
// Whatever case 3 does
}
switch(option) {
case 3:
case3();
case1();
break;
case 2:
case2();
case1();
break;
case 1:
case1(); // You didn't specify what to do for case 1, so I assume you want case1()
break;
default:
// Always a good idea to have a default, just in case demons are summoned
}
Of course case3(), case2()... are very poor method names, you should rename to something more meaningful about what the method actually does.
My suggestion is to not use fallthrough for anything except cases like the following:
switch (option) {
case 3:
doSomething();
break;
case 2:
case 1:
doSomeOtherThing();
break;
case 0:
// do nothing
break;
}
That is, giving several cases the exact same block of code to handle them (by "stacking" the case labels), making it more or less obvious what the flow is here. I doubt most programmers intuitively check for case fall through (because the indentation makes a case look like as a proper block) or can efficiently read code that relies on it - I know I don't.
switch(option)
{
case 3:
...
break;
case 2:
...
break;
}
... // code for case 1
You can custom the condition if you want to split cases
const { type, data } = valueNotifications
let convertType = ''
if (data?.type === 'LIVESTREAM' && type === 'NORMAL') {
convertType = 'LIVESTREAM1'
} else convertType = type
switch (convertType)
My use case has split the type from value notifications, but I have a specific LiveStream case which only shows in data.type is 'LIVESTREAM'
Something like this maybe.
switch(option) {
case 3: // code
// skip the next case, not break
// BLOCK-3
case 2: // code
if(option == 3) break;
// BLOCK-2
case 1: // code
// BLOCK-1
}
In switch statement if you don't break the subsequent case is executed. To give you simple example
int value = 2;
switch(value) {
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
case 3:
System.out.println("three");
break;
}
Will output
two
three
Because break wansn't executed on case 2

Categories

Resources