Showing posts with label if. Show all posts
Showing posts with label if. Show all posts

Monday, November 17, 2014

The Old Switcheroo

Let's talk about the 'switch' statement for a bit.  This is a form of conditional that is better suited to some tasks than if/else.

First, let's look at the structure of a switch:

switch(variable) {
    case value1:
        //Code to execute for value1
        break;

    case value2:
        //Code to execute for value1 or value2

    case value3:
        //Code to execute for value3
        break;

    default:
        //Code for any value other than the three above

}
// Done with switch

In detail.

If variable is equal to value1, we execute the code under 'case value1', then we 'break', which means we exit the current block (jump to 'Done with switch').

If variable is equal to value2, we execute the code under 'case value2', then continue to execute the code under 'case value3' before we hit the 'break' and head out to 'Done with switch'.

If variable has any other value, we execute the code under 'default'.

This is basically equivalent to:

if (variable == value1 || variable == value2) {
    if (variable == value1) {
        //Code to execute for value1;
    }
    //Code to execute for value1 or value2
}
else if (variable == value3) {
    //Code to execute for value3
}
else {
    Code for any value other than the three above
}

But I think in this case the switch is a bit easier to follow.

Sadly, the switch works with only a limited number of data types.  Basically it will work for atomic types that represent integer values, the objects that wrap those atomic types (like Integer or Long), and String.  It will also work with Enumerations, but I haven't written about those yet...  I guess I should get to those soon.

So, let's combine a for loop with a switch statement to get some output, shall we?

        for (int switchValue = 0; switchValue < 5; switchValue ++) {
            switch (switchValue) {
                case 0:
                    System.out.println("Just starting out.");
                    break;

                case 1:
                    System.out.println("Making progress.");
                    break;

                case 4:
                    System.out.println("All done.");
                    break;

                case 5:
                    System.out.println("We will never get here.");
                    break;

                default:
                    System.out.println("Getting there...");
                    break;
            }
        }


This runs a simple loop that goes from 0 to 4.  Along the way, we run a switch to execute various blocks of code based on that value.  The output from this block of code looks like this:

Just starting out.
Making progress.
Getting there...
Getting there...
All done.

If you follow the code, I hope this makes sense to you.  The 'default' statement catches anything that isn't 0, 1, 4 or 5, so it runs a couple of times in the middle.  If this is not clear, drop me a line and I'll try to improve it.

If I, if I, if I, if I Didn't Love you else I'd Hate You

At this point I'm sure I've written a bunch of if statements in various examples, but I want to discuss a few specifics.

So far, I've used only the simplest form:

if ( someConditionIsTrue ) {
    executeThisCode();
}

It actually doesn't get TOO much more complicated than that, but let's go into it anyway.

Let me just talk about what I mean by 'someConditionIsTrue':  What I mean is that we are evaluating what is within the parenthesis in order to determine whether the Java language considers this to be a 'true' value.  That doesn't mean some kind of universal truth, and it doesn't mean that it knows better than we do.  All it means is that if the language structure causes the boolean value 'true' to come out, we pass the test.  All of the following are 'true' to Java:

true

! false

1 == 1

1 != 53

(1+1) == 2

(1+2) == (4-1)

And it gets more complicated than that.  There are all sorts of expressions one can evaluate for truth, many times they are based on previous work your program has done.  You might for instance have a user enter their birth date, compare it against the current date, and decide that 'true' means 'older than 21 years'.  All you have to do is construct the expression correctly in order to suit the language's ability to decide based on what it considers to be truth.

OK, but what if someCondition ISN'T true?  The block doesn't execute, and we go on to the next line after the closing bracket, right?  But what if we want to do something because the condition is not true?

I guess we could do this:

if (conditionIsTrue) {
    doStuff();
}

if (conditionIsTrue == false) {
    doOtherStuff();
}

In fact, that would work fine.  Of course, if 'doStuff()' as a side effect changed the condition to false you would wind up executing both blocks.  I mean sure, doStuff() SHOULDN'T change that value, that's bad practice, but as an old C programmer I know very well that "shouldn't" doesn't necessarily mean "doesn't".

Besides, there's a cleaner way to express that concept:

if (conditionIsTrue) {
    doStuff();
}
else {
    doOtherStuff();
}

Isn't that better?  It makes the intention clear, it's less prone to side effects, and you finally get that one joke some programmer made on that forum you don't want anyone to know you visit.

You use 'else' to do things when the condition in an 'if' statement is false.  This will come in handy, and I'm sure I'll be using it soon in examples, so I wanted to make you familiar with it.

Another thing I should point out is that sometimes we need to make decisions based on not just simple true/false values, but combinations of such values.  maybe a user can be considered a 'favored customer' if they have either been a customer for two years or they have spent at least $1,000.00 with us.  That's where we get into what is called 'boolean logic'.  This is not too difficult to understand, and it's critical to get it locked down into your memory.  Please see the earlier post 'Hooray for Boo...leans' to get more information about this.  Just understand that almost anywhere that we can do a simple check for true/false, we can probably extend it to a more involved expression involving multiple terms combined in various ways.



View code here

Friday, November 14, 2014

Hooray for Boo..leans

I've mentioned booleans before, and it's critical to understand both boolean variables and boolean logic.  A great deal can be accomplished with booleans, for good or for ill.  You can make your programs sing or you can make yourself cry depending on how well you understand what you're doing.

I'm going to use the good old 'if' statement a lot in this post, but the same concepts apply to any conditional, such as while loops.

About the simplest possible boolean tests would be:

if (true) {

or

if (false) {

In fact, they're so simple that the java compiler should entirely remove either the test (in the first case) or the entire code block (in the second).  But logically, the first conditional should simply always execute whatever statement follows, and the second should just bypass the statement.

A more likely scenario would be this:

while(true) {

This is what is known as an infinite loop, which is handy when you mean it and devastating when you don't.  Create a while loop with a boolean condition that, due to some error, never switches to false, and you've got yourself a program that looks like it has 'locked up', when really it's happily executing the same thing over and over and over again.

Of course, most of the time you're going to be using logic, not constants, to determine how a conditional statement behaves.  This sort of thing is extremely common:

if ( someValue > 5 ) {

This expression, using the 'greater-than' conditional operator, evaluates to true if someValue is 6, or 22, or 25,101,793.  Just so long as it's more than five.  If it's five (or less) , it evaluates to false.  Say, that could come in handy...

Of course, you can also check for a value being less than another value with '<', or equal to another value with '=='.  You can get quickly more complex if you wish:

if ( value1 * 3 < value2 / 2 ) {

Is a perfectly valid expression.  Of course, you'd have to work out what values will do what, but it's not too conceptually difficult to understand that this will pass if value1 is 1 and value2 is 36, but fail if value1 is 1 and value2 is 2.

Boolean expressions can also be subjected to boolean operators, to evaluate more complex conditions.  For instance, let's say you've offering a discount to people who have been customers longer than five years AND have total orders of more than 1,000 dollars.  While you could write that as nested if statements:

if ( yearsAsCustomer > 5 ) {
    if ( totalOrders > 1000 ) {
        discountPercent = 1;
    }
}

(Note, I never said it was a GOOD discount)

You can simplify this to:

if ( yearsAsCustomer > 5 && totalOrders > 1000 ) {
    discountPercent = 1;
}

The '&&' operator joins two boolean values into one, and gives back true if and only if both of the values are true.

Boolean logic is generally summed up in a table like this:


OperatorValue1Value2Result
&&truetruetrue
&&falsetruefalse
&&truefalsefalse
&&falsefalsefalse


Note that last line:  && does NOT a check that both values are the same, it wants both values to be true before it gives up a true value.

The other operators are OR (||) and EQUALS (==).


OperatorValue1Value2Result
||truetruetrue
||falsetruetrue
||truefalsetrue
||falsefalsefalse

The OR operator is friendly.  As long as one of the operands is true, it gives you true.

OperatorValue1Value2Result
==truetruetrue
==falsetruefalse
==truefalsefalse
==falsefalsetrue
I think this one should be rather easy to understand.  If both operands have the same value, you get back that value.  Equals is a bit of a special case though, because you can use it with non-boolean operands as well.   (5 == 5) evaluates to true, as does (true == true).

So technically, you can do this (although my compiler warns me that I'm being silly when I do it, it reluctantly compiles and this can be run:

if ((5==5) == (true == true)) {
    System.out.println("Imagine that");
}

Note my use of parentheses to prioritize expressions.  I wanted to be absolutely sure that 5==5 and true == true both evaluated first, and I didn't want it to look like I was comparing 5 == true.  Now, the compiler follows standard rules for prioritizing mathematical operations, but extra parentheses can be very useful for we poor humans.

Expressions with booleans can be nested arbitrarily deep, although once you've got more than a few terms, they can be a bit difficult to work out.  Try to always give some thought to the next poor sod who has to modify your code, especially if that poor sod might be you again.

if ((isACustomer && (years > 10 || (years > 5 && sales > 1000))) || runningSpecialIncentives) {

Might be logically correct, and work just fine.  But do you want to add another condition to it first thing in the morning before you've had a cup of coffee?  Do you want to test it when someone is breathing down your neck?  This is probably a candidate for breaking up.  You can always create new booleans to act as placeholders:

boolean meetsQuotas = years > 10 || (years > 5 && sales > 1000);

Which would give the more readable:

if ((isACustomer && meetsQuotas) || runningSpecialIncentives ) {

Not only is it more readable as code, it almost makes sense as English.

The final boolean operator is !

No, that wasn't an expression of surprise.  The exclamation point is the 'NOT' operator.  It turns around the sense of any boolean expression, turning true into false and false into true.  Unlike the others I discussed above, which are binary operators (they work with two values), ! is a unary operator.  

!false == true

and

!true == false

So you can write:

if ( ! meetsQuotas && specialIncentives ) {
    System.out.println("We're giving a discount due to the special incentives program, but this guy is a cheapskate.");

That's about all I have to say about booleans for now.  Learn them, use them, love them.