Won't this just break out of the if statement? - java

So basically given the below code.
When action = 2; and mode = 1 Will i ever be set to 2?
I am working on a colleagues code, and it is written like this, but I thought that break would just skip the if and continue the rest of case 2. So basically the if statement is pointless.
switch(action){
case 1: i = 1; break;
case 2: if(mode == 1)
{
break;
}
i = 2;
break;
case 3: i = 3; break;
Ive rewritten this as:
case 2: if(mode != 1)
i = 2;
break;
But it is not the only place, and some more complex. If im going to refactor it I need some info that I am correct.

There's no such a thing as an "if loop." Break can never refer to an "if" statement.
See Wasserman's answer for a pointer to the language specification.
Also, assuming that 1 <= action <= 3, your code simplifies to:
if(! (action == 2 && mode == 1)) {
i = action;
}

JLS section 14.15:
A break statement transfers control out of an enclosing statement.
BreakStatement:
break Identifieropt ;
A break statement with no label attempts to transfer control to the innermost enclosing switch, while, do, or for statement (emphasis added) of the immediately enclosing method or initializer block; this statement, which is called the break target, then immediately completes normally.

your refactoring is correct if that's what you want to know.

If action == 2 and mode == 1, i = 2 will not be executed (why you don't test it? It would be faster than asking here).
But your improvement is anyways cleaner, I would use it.

Related

Behavior of switch statement with the default block at the top

I found one interesting way to use a switch statement in Java, and I can't catch all logic.
Can someone help to understand all details in depth?
Here is code:
private static int counter = 0;
public static Shape randomFactory() {
int xVal = rand.nextInt(100);
int yVal = rand.nextInt(100);
int dim = rand.nextInt(100);
switch (counter++ % 3) {
default:
case 0:
return new Circle(xVal, yVal, dim);
case 1:
return new Square(xVal, yVal, dim);
case 2:
return new Line(xVal, yVal, dim);
}
}
In general I understand this logic,
What exactly default mean here:
switch (counter++ % 3) {
default:
And how does switch (counter++ % 3) find equals case? And here isn't any brake presented.
Any suggestions?
default marks the block that would get executed if the switch expression does not match any case labels. In your example, default contains no break, so it would fall through and execute the same code as for case 0.
Note that, since you have a case label for every possible value of the switch expression, the default is effectively a no-op.
In your case you are using default block at the very beginning of case statement, which is a bit strange since default means that this part of code will execute if none of the case conditions have matched. You should also check about fall through. You avoided it with returns, but it is usually done with break.
switch (counter++ % 3) calculates first counter++ % 3 and then matches it with appropriate case.
The default clause is useless here: due to your %3 it should never happen.
Would you modify the %3 to %4 it would catch some data, but as there is neither a break nor a return statement it would execute just like case 0.
default:
It simply means of none of the conditions in switch statement are matched code corresponding to default will be executed.
default will execute when there is no matching in case.In this case default is useless since it will never execute. Consider the following case.
switch(input){
case 1:
// do something
break;
case 2:
// do something
break;
default:
// if input is not 1 or 2 this will execute.
break;
}
Default is one of the switch labels which contains statements to execute if none of the other labels match. From JLS §14.11:
At most one default label may be associated with the same switch statement.
If no case matches but there is a default label, then all statements after the matching default label in the switch block, if any, are executed in sequence. If all these statements complete normally, or if there are no statements after the default label, then the entire switch statement completes normally.
If no case matches and there is no default label, then no further action is taken and the switch statement completes normally.
So in this case default label will do nothing as there always will be a match.
There is no break inside default so it do nothing, it is just example of fallthrough.
Please read about switch statements from here -
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
default means if any case doesn't match with switch condition then default is called.
counter++ % 3 ..your counter was 0 so it will match with case 0.

Switch with if, else if, else, and loops inside case

For the purpose of my question I've only included case 1, but the other cases are the same. Let's say value is currently 1, we go to case 1 and our for loop goes through the array to see if each element matches with the whatever_value variable. In this case if it does, we declare the value variable to be equal to 2, and we break out of the loop. The problem is that when i highlight the other break(in eclipse), it says that the breaks are attached to the for statement as well, but i only wanted the for statement to be attached to the if statement, not the else if statements as well. I thought because there are no brackets for the for statement that it would only loop for the if statement but eclipse says otherwise(else if also loops from 0 to the length of the array).
switch (value) {
case 1:
for (int i = 0; i < something_in_the_array.length; i++)
if (whatever_value == (something_in_the_array[i])) {
value = 2;
break;
} else if (whatever_value == 2) {
value = 3;
break;
} else if (whatever_value == 3) {
value = 4;
break;
}
break;
case 2:
// code continues....
Your problem..... I think is that your for loop is encompassing all of the if, else if stuff - which acts like one statement, like hoang nguyen pointed out.
Change to this. Note the brackets that denote the code block on which the for loop operates and the change of the first else if to if.
switch(value){
case 1:
for(int i=0; i<something_in_the_array.length;i++) {
if(whatever_value==(something_in_the_array[i])) {
value=2;
break;
}
}
if(whatever_value==2) {
value=3;
break;
}
else if(whatever_value==3) {
value=4;
break;
}
break;
case 2:
code continues....
In this case, I'd recommend using break labels.
http://www.java-examples.com/break-statement
This way you can specifically call it outside of the for loop.
Seems like kind of a homely way of doing things, but if you must...
you could restructure it as such to fit your needs:
boolean found = false;
case 1:
for (Element arrayItem : array) {
if (arrayItem == whateverValue) {
found = true;
} // else if ...
}
if (found) {
break;
}
case 2:
If you need the for statement to contain only the if, you need to remove its else, like this:
for(int i=0; i<something_in_the_array.length;i++)
if(whatever_value==(something_in_the_array[i]))
{
value=2;
break;
}
/*this "else" must go*/
if(whatever_value==2)
{
value=3;
break;
}
else if(whatever_value==3)
{
value=4;
break;
}
but i only wanted the for statement to be attached to the if statement, not the else if statements as well.
Well get rid of the else then. If the else if is not supposed to be part of the for then write it as:
for(int i=0; i<something_in_the_array.length;i++)
if(whatever_value==(something_in_the_array[i]))
{
value=2;
break;
}
if(whatever_value==2)
{
value=3;
break; // redundant now
}
else if(whatever_value==3)
{
value=4;
break; // redundant now
}
Having said that:
it is not at all clear what you are really trying to do here,
not having the else part in the loop doesn't seem to make a lot of sense here,
a lot of people (myself included) think it is to always use braces ... so that people don't get tripped up by incorrect indentation when reading your code. (And in this case, it might help us figure out what you are really trying to do here ...)
Finally, braces are less obtrusive if you put the opening brace on the end of the previous line; e.g.
if (something) {
doSomething();
}
rather than:
if (something)
{
doSomething();
}

How to avoid code duplication?

Is it possible to avoid code duplication in such cases? (Java code)
void f()
{
int r;
boolean condition = true;
while(condition)
{
// some code here (1)
r = check();
if(r == 0)
break ;
else if(r == 1)
return ;
else if(r == 2)
continue ;
else if(r == 3)
condition = false;
// some code here (2)
r = check();
if(r == 0)
break ;
else if(r == 1)
return ;
else if(r == 2)
continue ;
else if(r == 3)
condition = false;
// some code here (3)
}
// some code here (4)
}
int check()
{
// check a condition and return something
}
A possible solution may be using Exceptions, but that doesn't seem to be a good practice.
Is there any so-called good pattern of program flow control in such cases? For example, a way to call break ; from inside the check() function.
(Possibly in other programming languages)
Some good answers (especially #Garrett's just now) to a tough question but I'll add my $0.02 for posterity.
There is no easy answer here about how to refactor this block without seeing the actual code but my reaction to it is that it needs to be redesigned.
For example, a way to call break ; from inside the check() function. (Possibly in other programming languages)
If you are asking for a different break that Java does not support (without a hack) and having the duplicated check() and various different loop exit/repeat code indicates to me that this is a large and complicated method. Here are some ideas for you to think about:
Each of the some code here blocks are doing something. If you pull those out to their own methods, how does that change the loop?
Maybe break the loop down into a series of comments. Don't get deep into the code but think about it conceptually to see if a different configuration drops out.
Have you had another developer in your organization who is not involved with this code take a look at it? If you explain in detail how the code works someone they may see some patterns that you are not since you are in the weeds.
I also think that #aix's idea of a finite state machine is a good one but I've needed to use this sort of mechanism very few times in my programming journeys -- mostly during pattern recognition. I suspect that a redesign of the code with smaller code blocks pulled into methods will be enough to improve the code.
If you do want to implement the state machine here are some more details. You could have a loop that was only running a single switch statement that called methods. Each method would return the next value for the switch. This doesn't match your code completely but something like:
int state = 0;
WHILE: while(true) {
switch (state) {
case 0:
// 1st some code here
state = 1;
break;
case 1:
state = check();
break;
case 2:
return;
case 3:
break WHILE;
case 4:
// 2nd some code
state = 1;
break;
...
}
}
Hope some of this helps and best of luck.
The best way to avoid this duplication is not to let it happen in the first place by keeping your methods small and focused.
If the // some code here blocks are not independent, then you need to post all the code before someone can help you refactor it. If they are independent then there are ways to refactor it.
Code smell
First of all, I second aix's answer: rewrite your code! For this, the state design pattern might help. I would also say that using break, continue and return in such a way is just as much a code smell as the code duplication itself.
Having said that, here is a solution, just for fun
private int r;
void f()
{
distinction({void => codeBlock1()}, {void => codeBlock4()}, {void => f()},
{void => distinction( {void => codeBlock2()},{void => codeBlock4()},
{void => f()}, {void => codeBlock3()} )
});
}
void distinction( {void=>void} startingBlock, {void=>void} r0Block, {void=>void} r2Block, {void=>void} r3Block){
startingBlock.invoke();
r = check();
if(r == 0)
r0Block.invoke();
else if(r == 1)
{}
else if(r == 2)
r2Block.invoke();
else if(r == 3)
// if condition might be changed in some codeBlock, you still
// would need the variable condition and set it to false here.
r3Block.invoke();
}
This uses closures. Of course the parameters r0Block and r2Block could be ommited and instead codeBlock4() and f() hard-coded within distinction(). But then distinction() would only be usable by f(). With Java <=7, you would need to use an Interface with the method invoke() instead, with the 4 implementations codeBlock1 to codeBlock4. Of course this approach is not at all readable, but so general that it would work for any business logic within the codeBlocks and even any break/return/continue-orgy.
Not really.
The second continue is redundant (your code would continue anyway).
Try using the Switch statement. It will make your code more readable.
One nicer way to do it would be to use switch statements, something like this:
void f()
{
int r;
boolean condition = true;
while(condition)
{
outerloop:
r = check();
switch(r){
case 0: break outerloop;
case 1: return;
case 2: continue;
case 3: condition = false;
}
You might want to think about re-formulating your logic as a state machine. It might simplify things, and will probably make the logic easier to follow.

Alternative to a goto statement in Java

What is an alternative function for the goto keyword in Java?
Since Java does not have a goto.
You could use a labeled BREAK statement:
search:
for (i = 0; i < arrayOfInts.length; i++) {
for (j = 0; j < arrayOfInts[i].length; j++) {
if (arrayOfInts[i][j] == searchfor) {
foundIt = true;
break search;
}
}
}
However, in properly designed code, you shouldn't need GOTO functionality.
There isn't any direct equivalent to the goto concept in Java. There are a few constructs that allow you to do some of the things you can do with a classic goto.
The break and continue statements allow you to jump out of a block in a loop or switch statement.
A labeled statement and break <label> allow you to jump out of an arbitrary compound statement to any level within a given method (or initializer block).
If you label a loop statement, you can continue <label> to continue with the next iteration of an outer loop from an inner loop.
Throwing and catching exceptions allows you to (effectively) jump out of many levels of a method call. (However, exceptions are relatively expensive and are considered to be a bad way to do "ordinary" control flow1.)
And of course, there is return.
None of these Java constructs allow you to branch backwards or to a point in the code at the same level of nesting as the current statement. They all jump out one or more nesting (scope) levels and they all (apart from continue) jump downwards. This restriction helps to avoid the goto "spaghetti code" syndrome inherent in old BASIC, FORTRAN and COBOL code2.
1- The most expensive part of exceptions is the actual creation of the exception object and its stacktrace. If you really, really need to use exception handling for "normal" flow control, you can either preallocate / reuse the exception object, or create a custom exception class that overrides the fillInStackTrace() method. The downside is that the exception's printStackTrace() methods won't give you useful information ... should you ever need to call them.
2 - The spaghetti code syndrome spawned the structured programming approach, where you limited in your use of the available language constructs. This could be applied to BASIC, Fortran and COBOL, but it required care and discipline. Getting rid of goto entirely was a pragmatically better solution. If you keep it in a language, there is always some clown who will abuse it.
Just for fun, here is a GOTO implementation in Java.
Example:
1 public class GotoDemo {
2 public static void main(String[] args) {
3 int i = 3;
4 System.out.println(i);
5 i = i - 1;
6 if (i >= 0) {
7 GotoFactory.getSharedInstance().getGoto().go(4);
8 }
9
10 try {
11 System.out.print("Hell");
12 if (Math.random() > 0) throw new Exception();
13 System.out.println("World!");
14 } catch (Exception e) {
15 System.out.print("o ");
16 GotoFactory.getSharedInstance().getGoto().go(13);
17 }
18 }
19 }
Running it:
$ java -cp bin:asm-3.1.jar GotoClassLoader GotoDemo
3
2
1
0
Hello World!
Do I need to add "don't use it!"?
While some commenters and downvoters argue that this isn't goto, the generated bytecode from the below Java statements really suggests that these statements really do express goto semantics.
Specifically, the do {...} while(true); loop in the second example is optimised by Java compilers in order not to evaluate the loop condition.
Jumping forward
label: {
// do stuff
if (check) break label;
// do more stuff
}
In bytecode:
2 iload_1 [check]
3 ifeq 6 // Jumping forward
6 ..
Jumping backward
label: do {
// do stuff
if (check) continue label;
// do more stuff
break label;
} while(true);
In bytecode:
2 iload_1 [check]
3 ifeq 9
6 goto 2 // Jumping backward
9 ..
If you really want something like goto statements, you could always try breaking to named blocks.
You have to be within the scope of the block to break to the label:
namedBlock: {
if (j==2) {
// this will take you to the label above
break namedBlock;
}
}
I won't lecture you on why you should avoid goto's - I'm assuming you already know the answer to that.
public class TestLabel {
enum Label{LABEL1, LABEL2, LABEL3, LABEL4}
/**
* #param args
*/
public static void main(String[] args) {
Label label = Label.LABEL1;
while(true) {
switch(label){
case LABEL1:
print(label);
case LABEL2:
print(label);
label = Label.LABEL4;
continue;
case LABEL3:
print(label);
label = Label.LABEL1;
break;
case LABEL4:
print(label);
label = Label.LABEL3;
continue;
}
break;
}
}
public final static void print(Label label){
System.out.println(label);
}
StephenC writes:
There are two constructs that allow you to do some of the things you
can do with a classic goto.
One more...
Matt Wolfe writes:
People always talk about never using a goto, but I think there is a
really good real world use case which is pretty well known and used..
That is, making sure to execute some code before a return from a
function.. Usually its releasing locks or what not, but in my case I'd
love to be able to jump to a break right before the return so I can do
required mandatory cleanup.
try {
// do stuff
return result; // or break, etc.
}
finally {
// clean up before actually returning, even though the order looks wrong.
}
http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
The finally block always executes when the try block exits. This
ensures that the finally block is executed even if an unexpected
exception occurs. But finally is useful for more than just exception
handling — it allows the programmer to avoid having cleanup code
accidentally bypassed by a return, continue, or break. Putting cleanup
code in a finally block is always a good practice, even when no
exceptions are anticipated.
The silly interview question associated with finally is: If you return from a try{} block, but have a return in your finally{} too, which value is returned?
The easiest is:
int label = 0;
loop:while(true) {
switch(state) {
case 0:
// Some code
state = 5;
break;
case 2:
// Some code
state = 4;
break;
...
default:
break loop;
}
}
Try the code below. It works for me.
for (int iTaksa = 1; iTaksa <=8; iTaksa++) { // 'Count 8 Loop is 8 Taksa
strTaksaStringStar[iCountTaksa] = strTaksaStringCount[iTaksa];
LabelEndTaksa_Exit : {
if (iCountTaksa == 1) { //If count is 6 then next it's 2
iCountTaksa = 2;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 2) { //If count is 2 then next it's 3
iCountTaksa = 3;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 3) { //If count is 3 then next it's 4
iCountTaksa = 4;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 4) { //If count is 4 then next it's 7
iCountTaksa = 7;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 7) { //If count is 7 then next it's 5
iCountTaksa = 5;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 5) { //If count is 5 then next it's 8
iCountTaksa = 8;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 8) { //If count is 8 then next it's 6
iCountTaksa = 6;
break LabelEndTaksa_Exit;
}
if (iCountTaksa == 6) { //If count is 6 then loop 1 as 1 2 3 4 7 5 8 6 --> 1
iCountTaksa = 1;
break LabelEndTaksa_Exit;
}
} //LabelEndTaksa_Exit : {
} // "for (int iTaksa = 1; iTaksa <=8; iTaksa++) {"
In modern Java I would just use switch and String. I am surprised that I couldn't find this answer:
for (String label = "start";;) {
switch (label) {
case "start":
...
case "something":
...
case "whatever":
...
label = "something"; break; // <== those two commands equal goto
...
default:
return;
}
}
Use a labeled break as an alternative to goto.
Java doesn't have goto, because it makes the code unstructured and unclear to read. However, you can use break and continue as civilized form of goto without its problems.
Jumping forward using break -
ahead: {
System.out.println("Before break");
break ahead;
System.out.println("After Break"); // This won't execute
}
// After a line break ahead, the code flow starts from here, after the ahead block
System.out.println("After ahead");
Output:
Before Break
After ahead
Jumping backward using continue
before: {
System.out.println("Continue");
continue before;
}
This will result in an infinite loop as every time the line continue before is executed, the code flow will start again from before.

Java Question: Is it possible to have a switch statement within another one?

I have a yes or no question & answer. I would like to ask another yes or no question if yes was the answer. My instructor wants us to use charAt(0) as input for the answer.
Is it possible to have a switch statement within another one (like a nested if statement)?
EDIT: Here is a sample of my pseudo code =
display "Would you like to add a link (y = yes or n = no)? "
input addLink
switch (link)
case 'y':
display "Would you like to pay 3 months in advance " + "(y = yes or n = no)?"
input advancePay
switch(advPay)
case 'y':
linkCost = 0.10 * (3 * 14.95)
case 'n'
linkCost = 14.95
case 'n'
linkCost = 0.00
Yes, but don't. If you need a further level of logic like that, place the second Switch in its own method with a descriptive name.
EDIT: By the example you've added, you've got two Boolean conditions. I would recommend against using switch at all, using if & else conditionals instead. Use (STRING.charAt(0) == 'y') as your test case, or something methodical like boolean isY(final String STRING) { return (STRING.charAt(0) == 'y' || STRING.charAt(0) == 'Y'); }
Yes. Switches break the language block statement pattern, but this is mainly because of C/C++ from which the switch statement used by Java is based.
In all three languages, the switch statement takes the following form:
switch(variable) {
case n:
statement 1;
statement n;
(optional) break;
case n+1:
statement 1;
statement n;
(optional) break;
// Optionally more statements
(optional) default:
statement 1;
statement n;
}
Because a switch statement breaks the traditional language pattern, many programmers wrap their multiple statements in a case using the traditional block style: { }
This is because most constructs in all three languages allow block style statements to be considered as one statement, but the switch statement does not require block style to execute multiple statements in a single case.
Without the break statement separating each case, there will be "fall through" - if case n was matched and did not have a break, the code under it (case n + 1) would be executed - if case n + 1 did not have a break and was matched, the default code would execute, if neither had a break, when matching case n, the code for case n, case n+1 and default would be executed.
The default is optional, and specifies a default action for a switch statement to execute. Typically, the default condition is either a generic handler, or a good place to throw an exception if the value could not logically be any other than the values in the switch statement.
To illustrate a switch statement executing inside a switch statement, take a look at this contrived example:
String message = null;
int outerVariable = getOuterVariable();
switch(outerVariable) {
case n:
statement 1;
statement n;
break;
case n+1:
int innerVariable = getInnerVariable();
switch(innerVariable) {
case 1:
message = "IT WAS 1";
break;
default:
message = "WHY WOULD YOU DO THIS? OH THE HUMANITY!";
}
break;
// Optionally more statements
(optional) default:
statement 1;
statement n;
}
It is possible, but that would be very convoluted and hard to read. There's almost certainly a better way, such as calling a method within the first switch statement and doing any more necessary processing (including another switch if necessary) in that method.
Most programming languages are orthogonal. That means, using a feature usually does not depend on the location, if meaningful.
For example, you cannot declare a local variable as public.

Categories

Resources