In documentation it is said you could equally use if-else multiple times or switch-case:
int condition;
setCondition(int condition) {
this.condition = condition;
}
Either switch-case
switch (condition) {
case 1: print("one"); break;
case 2: print("two"); break;
or
if (condition == 1) { print("one"); }
else if (condition == 2) { print("two"); }
Next, conditionis declared volatile and method setCondition() is called from multiple threads.
If-else is not atomic and volatile variable write is a synchronizing action. So both "one" and "two" string could be printed in the last code.
It could be avoided if some method local variable with initial value was used:
int localCondition = condition;
if (local condition == ..) ..
Does switch-case operator hold some initial copy of variable? How are cross threads operations implemented with it?
From the Java specification on switch statements:
When the switch statement is executed, first the Expression is evaluated. [...]
This suggests that the expression is evaluated once and that the result is temporarily kept somewhere else, and so no race-conditions are possible.
I can't find a definite answer anywhere though.
A quick test shows this is indeed the case:
public class Main {
private static int i = 0;
public static void main(String[] args) {
switch(sideEffect()) {
case 0:
System.out.println("0");
break;
case 1:
System.out.println("1");
break;
default:
System.out.println("something else");
}
System.out.println(i); //this prints 1
}
private static int sideEffect() {
return i++;
}
}
And indeed, sideEffect() is only called once.
The expression is evaluated once when entering the switch.
The switch may use the result internally as many times as it needs to determine what code to jump to. It's akin to:
int switchValue = <some expression>;
if (switchValue == <some case>)
<do something>
else if (switchValue == <some other case>
<do something else>
// etc
Actually, a switch compiles to a variety of byte code styles depending on the number of cases and the type of the value.
The switch only needs to evaluate the expression once.
Related
I would like to know if there is a way to execute a procedure at the end of each passage through a switch/case operator in Java ? (In the case of a switch in a loop for example)
Something like this 'after' operator (which do :
switch (constant) {
case a: return "x";
case b: return "y";
case c: return "z";
default: return "unknown";
after: alwayPassInThisMethodAfterBreakStatement()
}
I can't simply write my operation after the switch case statement because of the 'return' operation and I can't use a 'break' operation instead of 'return' because of my context.
You can use try-finally to guarantee the after method is called, and this avoids repeating the call per branch. Example:
try {
switch (constant) {
case 1: return "x";
case 2: return "y";
case 3: return "z";
default: return "unknown";
}
} finally {
alwaysCalledAtEnd();
}
There is no after or finally in a switch-case statement. You could build an if-else like:
if(yourvar==a) {
Alwaysmethod();
return x;
} else if(yourvar==b) {
Alwaysmethod();
return y;
} else if(yourvar==c) {
Alwaymethod();
return z;
} ..
But this makes no sense. You could put the method just after your switch-case or wherever your return arives so it would always be executed.
I am using a random number in a switch case. So have something like:
public void something {
Random myRand = new Random();
int number = myRand.nextInt(10 - 1) + 1;
switch(number)
case 1:
Do something and on completion go back and start running the something method again.
break:
case 1;
Do something and on completion go back and start running the something method again.
break;
Each case statement could be run through any number of times depending on input from user, some may not even be used.
What I would like is something inside the case statement saying :-
public void something (run);
Is what I am trying to do possible or is there a better way?
You can use do-while statement in this case with a condition to stop the execution.
Call your something method inside do while.
do {
something();
} while(condition);
This will call your method execute your switch case and again call your something method.
may i suggest you using interfaces?
what you are trying to implement is known as functional programming in which you pass functions as an argument to another functions
java supports functional programming in a way by using interfaces and has many built-in interfaces to ease-up the process
i recommend you to take a look at java.util.function package
now lets get on to your code
public void something(Supplier<Void> function) {
boolean condition = true; //use this boolean to control your loop
while (condition) {
Random myrand = new Random();
int number = myrand.nextInt(10 - 1) + 1;
switch (number) {
case 1:
function.get();
break;
case 2:
function.get();
break;
}
}
}
and you can call your "something" like this
public void Call() {
//if you want to declare the function only once
something(new Supplier<Void>() {
#Override
public Void get() {
System.out.println("the job is done!");
return null;
}
});
// if you already have a class implementing supplier
something(new MyFunction());
}
not that the Supplier interface is used because your function didn't have any inputs
you can also use Consumer, BiConsumer, Function, BiFunction .... for functions with inputs
The following code repeatedly calls the runSomeMethod() method for a random number of times.
Use a for loop:
public void something() {
Random myrand = new Random();
int number = myrand.nextInt(10 - 1) + 1;
for(int i=0 ; i<number ; i++) {
runSomeMethod();
}
}
concerned about your CASE syntax used
Solution goes as follows --> keep looping in a while loop
public void something {
boolean condition = true; // toggle this condition boolean to FALSE, when you want to break the loop
while(condition){
Random myrand = new Random();
int number = myrand.nextInt(10 - 1) + 1;
switch(number)
case 1;
Do something and on completion go back and start running the something method again.
break;
case 1;
Do something and on completion go back and start running the something method again.
break;
}
}
I'm reading some Java textbooks trying to learn a new language and I came across this method.
private String monthName (int month) { // bad example since this method needs to return a String
switch (month) {
case 1:
return "January";
case 2:
return "February";
...
case 12:
return "December";
}
}
The statement following this code says:
The compiler will reject this code because it is possible to reach the
end with- out returning a value.
So in Java, I assume that if a method has the word "String" before the method name, it MUST return a String? The problem with this switch statement is that perhaps no case statement condition is satisfied and execution just drops out of the bottom? Is it necessary for methods that are not labeled to void to ALWAYS return a value?
A method signature is a contract that specifies what it takes as arguments and what it is obligated to return. A method declared to return something other than void must either return something or throw something, it's not allowed to fall off the end without returning anything (if it did, the variable getting assigned the return value from the method call would still have to be assigned something).
Specifically, if a method is declared to return a String, either every possible path taken through that method must end with returning a String, returning null (null is an allowed value of any reference type), or throwing an instance of Throwable. That's what the quoted passage is telling you, the compiler can detect that you haven't done this and will complain about it.
Here you could have your code throw an exception if the integer passed in is not in the expected range. It's a good thing to have your methods validate that they are receiving reasonable values for their arguments. Using a default value or returning null is not as good because instead of exposing the problem immediately it sticks the caller with a value that may not make sense for it, and makes it harder to debug what happened because the place where the error is visible may be a long way from where the cause of the problem originated. This method could be written as:
private String monthName (int month) { // bad example since this method needs to return a String
switch (month) {
case 1:
return "January";
case 2:
return "February";
...
case 12:
return "December";
default:
throw new IllegalArgumentException("found unexpected value " + month);
}
}
so that the compiler won't complain, and any out-of-range values will come to your attention.
Be aware:
There is a convention many people adhere to that advocates that all switches should contain a default case, so that unhandled cases are not passed over silently.
The java.util Date/Calendar API numbers months from 0, not from 1 as in your example; if you use a Calendar to find a month and pass that int to this method it would be easy to return the wrong month. Error handling as near to the source as possible makes tracking down problems much easier.
No, I think the book is referring to the fact, that the compiler will go through the Switch statement, and if it doesn't hit case 1,2 or 12, then it won't return anything at all.
Any method that has a return type, must return that type. So in this example, you MUST return a String.
To fix that code, I'd do something like the following:
private String monthName (int month) { // bad example since this method needs to return a String
String retVal = "";
switch (month) {
case 1:
retVal = "January";
break; // essential in a switch statement
case 2:
retVal = "February";
break;
case 12:
retVal = "December";
break;
default:
retVal = "Invalid Month number";
break;
}
return retVal;
}
You may notice that I set the return value at the top of the method, then simply assign a value to it within the switch statement, then simply return the retVal at the end of the function. That way the compiler is satisfied. Another issue with your code sample is there are no break(s) in your switch/case block.
If that happens, then every single line would be executed regardless of which case is hit.
if a method has the word "String" before the method name, it MUST return a String
That is almost correct, it could also return a special value, 'null'.
It is possible for method to not return a value, in this case the String would instead be replaced with void, which indicates no return value.
Yes. A method that has a return type (in this case String) must always return a String.
Interestingly in this case, it's not straightforward why there is a compiler error. Let's simply to show why.
// Won't compile
String foo(boolean a) {
if (a) {
return "foo";
}
}
This throws a compiler error because not all branches of the program return something. It's possible to get to the end of the function (if a is not true) and still have not returned a String.
But it's not always the case that a method must end in a return statement. The compiler is smart enough to realize when all branches return.
// Compiles
String foo(boolean a) {
if (a) {
return "foo";
} else {
return "bar";
}
}
This will compile even though there is no return statement after the else because it figures out that each branch of the if/else ends in a return.
Let's move over to the switch statement.
// Won't compile
String foo(char c) {
switch (c) {
case 'a':
return "foo";
}
}
The above code will not compile, because for all inputs where c != 'a' there is no return statement. But we can fix that by adding a default.
// Compiles
String foo(char c) {
switch (c) {
case 'a':
return "foo";
default:
return "bar";
}
}
Here for all values of c, there is a return, so the compiler doesn't complain.
Let's look at some edges cases where the compiler isn't smart enough to do branch prediction.
// Won't compile
String foo(char c) {
if (c != 'a') {
return "bar";
}
switch (c) {
case 'a':
return "foo";
}
}
Compiler doesn't understand that going into the switch, 'c' must equal 'a' so even thought it might seem like this should compile it won't.
Here's a confusing case where all branches are covered, but the java compiler has still chosen to fail compilation.
// Won't compile
enum B { T, F }
String foo(B a) {
switch (a) {
case T:
return "foo";
case F:
return "bar";
}
}
It looks like the switch statement has all branch coverage. There are no other instances of B besides T and F. This can be solved by creating a default branch that handles new potential enum values.
This question already has answers here:
Difference between Return and Break statements
(14 answers)
Closed 5 years ago.
I am using a boolean that returns true. When something like this happens:
public boolean t(String label, String[] arguments) {
boolean j = false;
if (!j) {
return true;
}
return true;
}
However, inside of this boolean I have a switch statement. As you may know, you break out of switch statements usually. However I am doing something like this testing for booleans to be true or false. Would I return inside of a switch statement, or break if a boolean is false?
An example would be something like this:
switch (arguments.length) {
case 0:
if (j) return true;
break;
default:
break;
}
Which would be more useful, exchanging return true for break, or keep it the same?
A break statement would terminate execution of the switch statement and continue in the method. A return statement would leave the method entirely.
It's a matter of preference, really, as to which one is better. It comes down to method design.
I would say in most cases like you have above, it would be better to directly use a return statement and leave the method entirely.
That said, this:
public boolean t(String label, String[] arguments) {
boolean j = false;
if (!j) {
return true;
}
return true;
}
Can be simplified to this:
public boolean t(String label, String[] arguments) {
return true;
}
And if you're only checking one condition from one variable, then you don't need a switch statement; it's not as optimal.
I am doing something like this testing for booleans to be true or false
You shouldn't really "test" for boolean variables to be true or false, just return them.
Return call always returns the handler to the called function where as break in the switch statement is to avoid checking other cases present in the switch case. If you don want your program return any values then break is sufficient else return required.
So I had a previous question but realized I posted the wrong offending code. I've marked the offending statements below.
What I am trying to do is set the precedence for each of the operators with that switch statement.
Maybe someone could point me in the right direction.
Just as a note, I AM running JAVA 7 so String Switch will work.
Code
opType.java
import java.io.*;
public final class opType {
public static opType ADD = new opType( "Add" );
public static opType SUB = new opType( "Sub" );
public static opType MULT = new opType( "Mult" );
public static opType DIV = new opType( "Div" );
public static opType MOD = new opType( "Mod" );
public static opType LPAR = new opType( "LParen" );
public static opType RPAR = new opType( "RParen" );
protected String name;
private opType( String n )
{
name = n;
}
public String getName()
{
return name;
}
Operator.java
public class Operator extends Token {
protected opType val;
public boolean isOperator() { return true; }
public boolean isOperand() { return false; }
protected int getPrec()
{
switch(val.getName())
{
case "LParen":
{
return 0;
break; //unreachable
}
case "RParen":
{
return 0;
break; //unreachable
}
case "Mult":
{
return 1;
break; //unreachable
}
case "Div":
{
return 1;
break; //unreachable
}
case "Mod":
{
return 1;
break; //unreachable
}
case "Add":
{
return 2;
break; //unreachable
}
case "Sub":
{
return 2;
break; //unreachable
}
}
return 0;
}
public static int compare( Operator a, Operator b )
{
if( a.getPrec() == b.getPrec() )
return 0;
else if( a.getPrec() < b.getPrec() )
return -1;
else
return 1;
}
public opType getVal() { return val; }
public Operator( opType v ) { val = v; }
}
If you put a return, then the function returns before the break is executed and therefore the break will never be reached.
Instead you could use a variable that you set to a desired value and after the switch return that. Or just get rid of the break statements.
you already have return which will make the break unreachable
The reason that the code is unreachable is due to the return behaving like a break in that context - they both complete abruptly.
If a statement completes abruptly, then execution at that line is immediately returned to its appropriate context; if it's a break, it'll attempt to either exit the switch or return to its associated label if one exists; if it's a return, it will return to its caller, with or without a value.
This is why the code is unreachable: the line of code after the return can not be reached.
To really understand what that means or entails, we have to look at the Java Language Specification, specifically 14.1:
Every statement has a normal mode of execution in which certain
computational steps are carried out. The following sections describe
the normal mode of execution for each kind of statement.
If all the steps are carried out as described, with no indication of
abrupt completion, the statement is said to complete normally.
However, certain events may prevent a statement from completing
normally:
The break (§14.15), continue (§14.16), and return (§14.17) statements
cause a transfer of control that may prevent normal completion of
statements that contain them.
Evaluation of certain expressions may throw exceptions from the Java
Virtual Machine (§15.6). An explicit throw (§14.18) statement also
results in an exception. An exception causes a transfer of control
that may prevent normal completion of statements.
If such an event occurs, then execution of one or more statements may
be terminated before all steps of their normal mode of execution have
completed; such statements are said to complete abruptly.
An abrupt completion always has an associated reason, which is one of
the following:
A break with no label
A break with a given label
A continue with no label
A continue with a given label
A return with no value
A return with a given value
A throw with a given value, including exceptions thrown by the Java
Virtual Machine
The terms "complete normally" and "complete abruptly" also apply to
the evaluation of expressions (§15.6). The only reason an expression
can complete abruptly is that an exception is thrown, because of
either a throw with a given value (§14.18) or a run-time exception or
error (§11, §15.6).
If a statement evaluates an expression, abrupt completion of the
expression always causes the immediate abrupt completion of the
statement, with the same reason. All succeeding steps in the normal
mode of execution are not performed.
Unless otherwise specified in this chapter, abrupt completion of a
substatement causes the immediate abrupt completion of the statement
itself, with the same reason, and all succeeding steps in the normal
mode of execution of the statement are not performed.
Unless otherwise specified, a statement completes normally if all
expressions it evaluates and all substatements it executes complete
normally.
The return statement effectively exits the method immediately. Since you've placed return statements inside the switch block for each case, whichever case is matched will, according to your code, return whatever value is indicated immediately. The break therefore cannot be executed, hence the error. You have two options:
1- Set a value, and return at the end of the method:
protected int getPrec(){
int prec = 0;
switch(val.getName()) {
case "LParen":
prec = 0;
break;
case "RParen":
prec = 0;
break;
case "Mult":
prec = 1;
break;
case "Div":
prec = 1;
break;
case "Mod":
prec = 1;
break;
case "Add":
prec = 2;
break;
case "Sub":
prec = 2;
break;
default:
prec = 0;
break; // technically unnecessary since we're at the end already but adding for completeness.
}
return prec;
}
2- Ditch the break; statements and keep the return statements as you've written them.
Personally I would prefer the first option as its cleaner and more readable to me. Plus it makes it easier to expand whatever actions need to be done in one or more cases if need be in the future.
By the way, watch your naming convention. You presently have:
public final class opType // bad naming
Since this is a class, the Java standard is to capitalize the first letter of the class. So it should be:
public final class OpType // good naming
Here you can comment the line return super.onOptionsItemSelected(item)
after commenting this line the code will run.
This Works for me
public boolean onOptionsItemSelected(MenuItem item) {
//return super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.aboutUS:
Intent i = new Intent("com.code.myapp.ABOUT");
startActivity(i);
break;
case R.id.preferences:
break;
}
return false;
}