Given a simple if statement in the form
public static String test(boolean flag) {
if (!flag) {
return "no";
} else {
System.out.println("flag enabled");
}
return "yes";
}
or
public static String test(final boolean flag)
{
if (flag)
{
System.out.println("flag enabled");
return "yes";
}
else
{
return "no";
}
}
Eclipse gives me the warning, underlining the whole else block
Statement unnecessarily nested within else clause. The corresponding then clause does not complete normally
However, this...
public static String test(final boolean flag)
{
if (flag)
{
System.out.println("flag enabled");
return "yes";
}
return "no";
}
does not give the warning.
this question seems related, but I'm not using return in the else of the first example, and else is not finally.
I understand that this is simply a preference, and that it can be turned off. However, I don't like ignoring things simply because I don't understand what is the problem. And I can't seem to find any documentation on why Eclipse added this as a configurable warning.
So in all, What does The corresponding then clause does not complete normally mean? What is the problem that this warning is trying to protect me from?
You can remove the else clause and that will remove the warning.
To answer your other question, "The corresponding then clause does not complete normally" is referring to the fact that the "then" clause has a return statement. Completing "normally" means control flow continues to the statements after the "else" block, but this doesn't happen since you returned.
There is no logical, functional, or runtime difference between:
// Gets warning
public static String test(final boolean flag) {
if (flag) {
System.out.println("flag enabled");
return "yes";
} else {
return "no";
}
}
and
// Doesn't get warning
public static String test(final boolean flag) {
if (flag) {
System.out.println("flag enabled");
return "yes";
}
return "no";
}
So it boils down to a style preference. Why might Eclipse think this is worth a warning? Think of it as similar to "unreachable code" -- an aspect of the code is unnecessarily (and perhaps unusually) verbose, and this usually merits another look to ensure that no logic errors are hiding. If I wrote the first code snippet and got the warning, I'd be thankful for Eclipse and happily improve the code, arriving at the second snippet. But again, that's just because I prefer the second snippet.
Here's a scenario where this might come into play and affect functionality (unintentionally). Suppose the code originally looks like this:
// Returns true if the dog was fed
boolean feedDog(Dog dog) {
if (!dog.isHungry()) {
return false;
}
Food food;
if (dog.isBadToday()) {
food = getDefaultFood();
} else {
food = getTreat();
}
dog.feed(food);
return true;
}
Sometime later, the team decides that feedDog should only return true if the dog was fed a treat. What if the code is modified to:
// Returns true if the dog was fed *a treat*
boolean feedDog(Dog dog) {
if (!dog.isHungry()) {
return false;
}
Food food;
if (dog.isBadToday()) {
food = getDefaultFood();
return false; // Dog wasn't fed a treat
} else {
food = getTreat();
}
dog.feed(food);
return true;
}
Now there's a bug because the programmer went with the shortest change that "looked right at first glance" -- the poor dog doesn't get fed if it misbehaved. Eclipse's warning is saving the dog here, telling the programmer to pay attention to the logic surrounding the if statement, which doesn't seem right anymore (according to Eclipse). Hopefully the programmer will heed the warning and avoid returning from the if block:
// Returns true if the dog was fed *a treat*
boolean feedDog(Dog dog) {
if (!dog.isHungry()) {
return false;
}
Food food;
boolean fedTreat = false;
if (dog.isBadToday()) {
food = getDefaultFood();
} else {
food = getTreat();
fedTreat = true;
}
dog.feed(food);
return fedTreat;
}
Related
To summarize I am making a program for a metro ticket system. and I am using set and get methods for it, when it comes to boolean values (since I need to validate that the person enters enough money for the ticket) how am i supposed to put in the main class( it is defined in brain) using the set method and an if statement.Here is a little fraction of the entire code and the rest is on github(https://github.com/alexxei4/subwayticket). The main is basically the class that will be used for interaction with the user and the brain is where alot of the actions are defined.All help is appreciated, please and thank you.
if (Choice1a == 10){
if(subway1.ticketcounter1(true);){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
if(subway1.ticketcounter1(false);){
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
This is not how you evaluate boolean values, you just place the value in an if statement and it will proceed if true and refuse if false, also there is no need to duplicate the statement when you can just place an else block to handle situations that are not true:
if(subway1.ticketcounter1) {
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
else {
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
Also do not include semicolons in if statements, that's incorrect syntax. Read more about how to use use boolean values here: https://codingbat.com/doc/java-if-boolean-logic.html
EDIT:
After reading through your Github code I see that ticketcounter1 indeed is a method, but what it's doing is trying to change the value of ticketcounter1 like it's a referenced object, but boolean are primitive data types and can't be referenced, and even if they could it still wouldn't work because Java is a pass-by-value language. Read here for more information on that.
public void ticketcounter1(boolean ticketcounter1){
if (credit1 > total1){
ticketcounter1 = true;
}
else {
ticketcounter1 = false;
}
}
public void ticketcounter2(boolean ticketcounter2){
if (credit2 > total2){
ticketcounter2 = true;
}
else {
ticketcounter2= false;
}
Like the other answer said you should be returning the value as boolean instead of trying to change it:
public boolean ticketcounter1(){
if (credit1 > total1){
return true;
}
else {
return false;
}
}
public boolean ticketcounter2(){
if (credit2 > total2){
return true;
}
else {
return false;
}
}
But all in all your code demonstrated fundamental flaws in understanding how the language works, I would suggest picking up a good Java for beginners kind of book or do some introductory online tutorials. Here is a good place to start your learning journey: https://docs.oracle.com/javase/tutorial/java/index.html
You code is like this
public void ticketcounter1(boolean ticketcounter1){
if (credit1 > total1){
ticketcounter1 = true;
}
else {
ticketcounter1 = false;
}
}
public void ticketcounter2(boolean ticketcounter2) {
if (credit2 > total2){
ticketcounter2 = true;
}
else {
ticketcounter2= false;
}
}
It should be like this. Instead of using the variable and passing it though parameter. Use getter. Besides that your code won't run since subway1.ticketcounter1(true) is giving nothing. It is only changing variables stored in Brain.java. No information is being sent to main.
public boolean ticketcounter1(){
if (credit1 > total1){
return true;
}
else {
return false;
}
}
public boolean ticketcounter2(){
if (credit2 > total2){
return true;
}
else {
return false;
}
}
You can create functions without parameters. I don't know what were you trying to do?
if (Choice1a == 10){
if(subway1.ticketcounter1()){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
if(subway1.ticketcounter1()){
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
}
subway1.ticketcounter1() will give either true and false. Do not use ; in if statement condition. ; ends the statement. Check this guide to learn about use of semi-colon If you do want to use ; The code should look like this
if (Choice1a == 10){
boolean ticketCounter1 = subway1.ticketcounter1();
if(ticketCounter1){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
} else {
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
}
P.S You don't need two ifs if-else would be better in this case
if(condition) {
// Conditions is true
} else {
// Condition is false
}
Why isn't this structure acceptable? Anyway it returns a boolean value right??
public boolean a()
{
if(condition)
{
if(condition)
{
if(condition)
{
return true;
}
}
}
}
It's not valid because there is a possibilty where nothing is returned. Your method is declared as returning a boolean value, so it MUST return a boolean value at some point in the code before the method is finished, regardless of the inner logic. If your if-statement if (condition) is false, the method doesn't have another return statement, so the code won't even compile. To fix this, add a "default" return value:
public boolean a()
{
if(condition)
{
if(condition)
{
if(condition)
{
return true;
}
}
}
return false;
}
Not valid because you need to do a return some default value (return) .
What if conditions not satisfied ??
valid is :
public boolean a()
{
if(condition)
{
if(condition)
{
if(condition)
{
return true;
}
}
}
return false;
}
As a side note,To make your code mode readable,I suggest
if(condition && condition && condition)
{
return true;
}
return false;
Prefer to read jls-14.17
Though the method returns true when the condition is satisfied, it doesn't specify a return value when the condition isn't satisfied. The method should cover all the code paths (read conditional statements).
As the answers above correctly state, you absolutely have to return something in Java. C doesn't really care.
In order to avoid this I would recommend decreasing the level of nesting to do something like
boolean value=false; //default return
if(cond && cond)
return value;
if(cond)
return false; //if you want to be more specific
if(cond)
value=true;
return value;
so a value gets returned no matter what. On the plus side, readability increases
Got probably a simple problem but where ever I google it it seems the problem
is a semicolon at the end of the if statement, the problem is eclipse giving me the syntax error asking to delete my else on the else if statement, this happens nearly all the time for me and i end up using multiple IF's.
if(saleStatus == false || offerPrice <= currentOffer)
{
System.out.print("Error, sale is not open");
return false;
}
else if(currentOffer >= reservePrice)
{
saleStatus = false;
}
Every path your function can take must return a value, if you specify that it will return something.
In this case, you have probably specified it as
access_modifier boolean function_name(params){
... // ^return type
}
So, all code paths must return a boolean.
In your code, if it takes the else... path, and exits without returning anything, that isn't permitted.
else if(currentOffer >= reservePrice)
{
saleStatus = false;
//return something here (null if you don't care)
}
//or return something here (which all code-paths hit)
If you use an IDE like Eclipse, it can warn you in advance about things like this.
There's no return statement in your else block. If a return type is declared in your method, the method would not know what to return if the code enters the else block.
Put one in it or after (*).
In the first if, you return a value, so there is no point on specifying "else" because the rest of the method is not executed.
Some developers avoid multiple return statements in functions for code quality.
I wrapped your code in a class declaration, with minimum additional declarations, and a return after the whole if-else structure, and Eclipse shows no errors. I suggest writing a similarly minimal complete program that does show the problem, and posting it.
You do not need "else if" rather than "if" for the second test, but it should be harmless.
public class Bad {
boolean saleStatus;
int offerPrice;
int currentOffer;
int reservePrice;
public boolean problem() {
if(saleStatus == false || offerPrice <= currentOffer)
{
System.out.print("Error, sale is not open");
return false;
}
else if(currentOffer >= reservePrice)
{
saleStatus = false;
}
return true;
}
}
I have a function when has an if-else statement. It essentially looks like this:
if(boolean == true)
{
// do something
boolean = false;
}
else if(boolean == false)
{
// do the other thing
boolean = true;
}
Now, my understanding is that the if statement will exit and return control to the function and then continue according to the changed boolean value. But I'm clearly missing something because my code is not exiting the original 'if'/'else if' statement (whichever the original case). Can anyone tell me what I've missed?
Well as requested, additional data about the code is that it is a part of my android project and each condition in the if-else block has a nested function and the boolean(global) value is being set/unset withing these functions. So the code now looks like this:
dummyFunction(){
boolean = checkIfTrueOrFalse();
if (boolean) {
onClick( public void onClick(){
// do something
boolean = false;}
} else if(boolean == false){
onClick( public void onClick(){
// do something
boolean = true;}
}
}
Any ideas?
if(boolean == true)
{
// do something
boolean = false;
}
if (boolean == false)
{
// do the other thing
boolean = true;
}
When you do this, then the program will flow to the second condition. In an if/else if statement, if the if statement has been satisfied, then the program will ignore the else if block.
Your current code simply flows through the first if block and then skips the else if statement to end the block.
void someMethod()
{
boolean aBoolean = true;
if(aBoolean == true)
{
// do something
aBoolean = false;
}
else if(aBoolean == false)
{
// do the other thing
aBoolean = true;
}
}
When someMethod will execute, since aBoolean is assigned with true, control will come to if block cause the condition becomes true. if it was false, then the control will come to else part.
We have many good answers/comments already but just wanted to add something here -
1.
if (condition) {
} else {
}
is a single code construct. The condition will be evaluated at the beginning at run time and java will decide which block to execute i.e. the if block or the else block. Only 1 of the 2 can be executed.
Java allows us to nest if/else. That means we can have something like below -
if(condition1){
} else if (condition2) {
} else if (condition3) {
} else {
}
It is effectively same as below -
if (condition1) {
} else {
if (condition2) {
} else {
if (condition 3) {
} else {
}
}
}
Here, it should be noted that only the block which satisfies the condition will be executed. If none of the conditions is met, then the inner most else will be executed (i.e. the else block of condition3 )
Finally, I feel that your confusion is between the below blocks
boolean aBoolean = true;
if(aBoolean == true)
{
// do something
aBoolean = false;
} else if(aBoolean == false)
{
// do the other thing
aBoolean = true;
}
VS
boolean aBoolean = true;
if(aBoolean == true)
{
// do something
aBoolean = false;
}
if(aBoolean == false)
{
// do the other thing
aBoolean = true;
}
In the latter of the 2 examples, there are 2 independent if blocks and both will get executed (off course, this is not logically correct but it is a legal java code.)
Could you provide more info regarding your code not exiting either of the 2 blocks? Doing System.out.println() of variables within your blocks might be able to help you determine why your code is not exiting.
You could use an if/else pair instead of an if/else-if as the parameter that your code depends on is would be either true/false. If the if-block is not satisfied, automatically the else-block would be traversed.
Your code is actually a shortcut for
if (boolean) {
// do something
boolean = false;
} else {
if (!boolean) {
// do the other thing
boolean = true;
}
}
Written this way, it maybe becomes clearer that the inner if nested in the else case will not be processed if the first if condition was already met.
Well I've solved it (taking inputs from here of course). I just added a call to the function within the nested functions and it worked. Now the code looks like this:
public static void dummyFunction(){
boolean = checkIfTrueOrFalse();
if (boolean) {
onClick( public void onClick(){
// do something
dummyFunction();
boolean = false;}
} else if(boolean == false){
onClick( public void onClick(){
// do something
dummyFunction();
boolean = true;}
}
}
I have a history in programming, but not much in software development. I'm currently writing a piece of software for the company I work at, and I've come to challenge myself on the readability of my code.
I want to know whether this is a "valid" alternative to embedded if statements, or if there is anything better I could use.
Let's say I have the following method:
public void someMethod()
{
if (some condition)
{
if (some condition 2)
{
if (some condition 3)
{
// ...etc all the way until:
doSomething();
}
else
{
System.err.println("Specific Condition 3 Error");
}
}
else
{
System.err.println("Specific Condition 2 Error");
}
}
else
{
System.err.println("Specific Condition 1 Error");
}
}
Now the first thing I should point out is that in this instance, combining the conditions (with &&) isn't possible, since each one has a unique error that I want to report, and if I combined them I wouldn't be able to do that (or would I?). The second thing I should point out before anyone screams "SWITCH STATEMENT!" at me is that not all of these conditions can be handled by a switch statement; some are Object specific method calls, some are integer comparisons, etc.
That said, is the following a valid way of making the above code more readable, or is there a better way of doing it?
public void someMethod()
{
if (!some condition)
{
System.err.println("Specific Condition 1 Error");
return;
}
if (!some condition 2)
{
System.err.println("Specific Condition 2 Error");
return;
}
if (!some condition 3)
{
System.err.println("Specific Condition 3 Error");
return;
}
doSomething();
}
So basically, instead of checking for conditions and reporting errors in else blocks, we check for the inverse of the condition and return if it is true. The result should be the same, but is there a better way of handling this?
If I was being particularly pedantic I would use something like this.
boolean c1, c2, c3;
public void someMethod() {
boolean ok = true;
String err = "";
if (ok && !(ok &= c1)) {
err = "Specific Condition 1 Error";
}
if (ok && !(ok &= c2)) {
err = "Specific Condition 2 Error";
}
if (ok && !(ok &= c3)) {
err = "Specific Condition 3 Error";
}
if ( ok ) {
doSomething();
} else {
System.out.print(err);
}
}
You are now single-exit AND flat.
Added
If &= is difficult for you, use something like:
if (ok && !c3) {
err = "Specific Condition 3 Error";
ok = false;
}
I would write it as
if (failing condition) {
System.err.println("Specific Condition 1 Error");
} else {
somethingExpensiveCondition2and3Dependon();
if (failing condition 2)
System.err.println("Specific Condition 2 Error");
else if (failing condition 3)
System.err.println("Specific Condition 3 Error");
else
doSomething();
}
yes, your code in both cases smells of conditional complexity (code smells)
Java is an OOP language, so your code should be factored to in the spirit of OOD, something like this:
for (Condition cond : conditions) {
if (cond.happens(params))
cond.getHandler().handle(params);
}
conditions list should be injected to this class, this way when a new condition is added or removed the class doesn't change. (open close principle)
Your second approach is fairly good. If you want something a little more baroque, you can move your conditions into Callable objects. Each object can also be provided with a way of handling errors. This lets you write an arbitrarily long series of tests without sacrificing functionality.
class Test {
private final Callable<Boolean> test;
private final Runnable errorHandler;
public Test(Callable<Boolean> test, Runnable handler) {
this.test = test;
errorHandler = handler;
}
public boolean runTest() {
if (test.call()) {
return true;
}
errorHandler.run();
return false;
}
}
You could then organize your code as follows:
ArrayList<Test> tests;
public void someMethod() {
for (Test test : tests) {
if (!test.runTest()) {
return;
}
}
doSomething();
}
EDIT
Here's a more general version of the above. It should handle almost any case of this type.
public class Condition {
private final Callable<Boolean> test;
private final Runnable passHandler;
private final Runnable failHandler;
public Condition(Callable<Boolean> test,
Runnable passHandler, Runnable failHandler)
{
this.test = test;
this.passHandler = passHandler;
this.failHandler = failHandler;
}
public boolean check() {
if (test.call()) {
if (passHandler != null) {
passHandler.run();
}
return true;
}
if (errorHandler != null) {
errorHandler.run();
}
return false;
}
}
public class ConditionalAction {
private final ArrayList<Condition> conditions;
private final Runnable action;
public ConditionalAction(ArrayList<Condition> conditions,
Runnable action)
{
this.conditions = conditions;
this.action = action;
}
public boolean attemptAction() {
for (Condition condition : conditions) {
if (!condition.check()) {
return false;
}
}
action.run();
return true;
}
}
One might be tempted to add some sort of generic data that could be passed around to share info or collect results. Rather than doing that, I'd recommend implementing such data sharing within the objects that implement the conditions and action, and leave this structure as is.
For this case, that's about as clean as you are going to get it, since you have both custom criteria and custom responses to each condition.
What you are in essence doing is validating some conditions before calling the doSomething() method. I would extract the validation into a separate method.
public void someMethod() {
if (isValid()) {
doSomething();
}
}
private boolean isValid() {
if (!condition1) {
System.err.println("Specific Condition 1 Error");
return false;
}
if (!condition2) {
System.err.println("Specific Condition 2 Error");
return false;
}
if (!condition3) {
System.err.println("Specific Condition 3 Error");
return false;
}
return true;
}
Nope, that's about what you get in Java. If you have too many of these, it may indicate that you should refactor a bit, and possibly even rethink your algorithm -- it may be worthwhile trying to simplify it a bit, because otherwise you're going to come back to the code in a few months and wonder why the heck a + b + c + d = e but a + b' + c + d = zebra
The second option you have is the more readable one. While multiple returns are usually not recommended putting all of them at the beginning of the code is clear (it isn't as if they are scattered all over the method). Nested ifs on the other hand, are hard to follow and understand.