Showing posts with label variables. Show all posts
Showing posts with label variables. Show all posts

Wednesday, November 11, 2015

Stop giving me so much static

Let's talk about the keyword static for a moment.

There are two different uses for this in our code.  It can be applied to methods or it can be applied to variables.

When static is applied, it disassociates the item being declared from any specific instance of the class.  For methods, this means that the method can be called by anyone at any time without creating a new class of that type.  This can be particularly handy for utility functions, initializers, or any other chunk of code that wants to run without caring that it's about a particular person, bill, or list of stocks.  For variables, it mostly means that the value is shared across all instances of the class.

Static Methods

Static methods can be called without making a new class.  For instance, it could be used for a factory method, which is a design pattern that calls for objects to be built by calling a function to do so.

public class Person {
    ...
    public static Person createPerson(firstName, lastName) {
        ...
    }
}

You can call createPerson without having a Person object, like so:

Person.createPerson("John", "Doe");

Many utility functions are declared as static, and as a general rule they will need to operate free of any context supplied by objects.

Static Variables

Static variables come from the same basic idea of being disassociated from any specific instances of the class.  They're useful for maintaining overall context, for instance, if we want to keep track of how many Person objects we've created we could write something like this:

public class Person {
    ...
    private static int numberCreated = 0;
    ...
    public static Person createPerson(firstName, lastName) {
        ...
        numberCreated ++;
        ...
    }
}

Now, every time we invoke createPerson, we'll also be incrementing the value of numberCreated, and it will always be available as a statistic our programs can check.

Many times, inexperienced programmers will overuse static methods, because when they first start creating methods and functions, they just call them from main.  Your main method has to be static, and if you try calling non-static methods directly from it, the compiler complains.  So the path of least resistance is often seen as just making those other methods static too.  This does seem to work, but it goes against object oriented design principals, and it's best to nip this in the bud.  So they start with this:

public class OutputTest {
    ...
    private PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        print("This is a test");
    }
    ...
    public void print(String message) {
        outputStream.println(message);
    }
}

But that fails because you can't call 'print' from a static context, so they change it to this

public class OutputTest {
    ...
    private PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        print("This is a test");
    }
    ...
    public static void print(String message) {
        outputStream.println(message);
    }
}

That fails, too, because outputStream isn't static, so they change the code again:

public class OutputTest {
    ...
    private static PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        print("This is a test");
    }
    ...
    public static void print(String message) {
        outputStream.println(message);
    }
}

And they're satisfied.  Everything works now!  I call this the static cascade, and I recommend avoiding it.  If you did not originally intend for these items to be shared and free of binding to specific objects, then don't go changing them to act that way.  

Get used to writing object oriented code.  Do this instead:

public class OutputTest {
    ...
    private PrintStream outputStream = ...;
    ...
    public static void main(String [] args) {
        OutputTest test = new OutputTest();  //The key!
        test.print("This is a test");
    }
    ...
    public void print(String message) {
        outputStream.println(message);
    }
}

While it might be a bit more of a conceptual leap, it's actually a far smaller change to the original code, and it opens your class up to being more adaptable to use in other systems.  It's also a necessary step towards object oriented thinking, so you might as well get it over with now.

It's the final countdown!

Many times we declare a variable that we really ought not to change, at least in some particular spot.  We can just remember not to change it, and that might work.  A better solution is to let the language keep us from even trying, and Java offers us the final keyword for this purpose.

A variable declared as final cannot be changed, so maybe the word 'variable' does not even really apply, so we can call them 'constants' if we like.  This has a couple of different purposes.  First off, we might want to set up a constant like an approximation of pi for use in a class that does geometric calculations:

static final float pi = 3.14159;

Now any code that tries to change pi will be flagged by the compiler as a problem.

Another use for the final keyword is to make sure that methods don't modify parameters we've given them:

public void calculateValue (final int quantity) {

This would make sure that we don't accidentally change quantity somewhere inside the calculateValue method.

The compiler is able to simplify the code that it generates for variables declared as 'final', so we get that benefit, too.  In short, it's a good idea to declare things as final whenever it's reasonably possible to do so.

Tuesday, February 10, 2015

It's a SERIES OF TUBES!

I've been struck in recent days by a number of posts over at /r/javahelp, all with the same basic theme.  They've got some code, and it references a variable name that is declared elsewhere in the program.  These nascent developers don't yet understand that just because you mention a variable in one place, that doesn't mean it's available elsewhere.

It is fundamentally important to understand the issue of scope if you ever hope to write programs well.  Where you declare things, and what keywords you use when you do so, have a huge effect on the visibility of your variables.

For instance, I often see issues that boil down to an attempt at doing this:

void multiplyTwoNumbers(int numberOne, int numberTwo) {
    int numberThree = numberOne * numberTwo;
}

"It doesn't work" they say, or "it doesn't do anything".  My friends, it does exactly what you told it to.  It's just that you didn't tell it to do anything particularly useful.  When this method is finished, it will have multiplied numberOne by numberTwo and assigned its value to numberThree.  Then it's done.

Some folks go a bit further:

void callingMethod() {
    int numberThree;
    multiplyTwoNumbers(5,10);
    System.out.println("See?  It didn't work! " + numberThree);
}

And they're right, it didn't.

The reason is that the two variables named 'numberThree' are entirely independent of each other.  One of them is really 'callingMethod->numberThree' and the other one is 'multiplyTwoNumbers->numberThree' and they have never met.

Naming things the same is meaningless.  It might help us to understand our code better, but as far as Java is concerned the variables might as well be called Ben and Jerry.  Mmmm, Ben and Jerry.

If you really want callingMethod->numberThree to take on the value you calculated in 'multiplyTwoNumbers' you need to explicitly lay it out.  Just as you can't expect your sink to drain properly into the sewer system if you don't actually provide a continuous connection, you can't expect what one method does to just be known by another method.

So make sure you declare multiplyTwoNumbers as an int.  Make sure you actually return the value of numberThree at when it's done:

int multiplyTwoNumbers(int numberOne, int numberTwo) {
    int numberThree = numberOne * numberTwo;
    return numberThree;
}

That will help.  You've now installed the pop-up drain thingie in the bottom of the sink bowl.  Let's finish the job:

void callingMethod() {
    int numberThree;
    numberThree = multiplyTwoNumbers(5,10);
    System.out.println("It verks! " + numberThree);
}

This is so important to understand.  Local variables go away as soon as the local block (code between { and }) comes to and end.  If you don't provide a method for the value to escape the block, it's going to go to the big heap in the sky.

Perhaps part of the problem is that people get confused by the fact that they can do this:

public class Wizz {

    int wizzLevel = 0;

    public void bumpWizzLevel() {
        wizzLevel = wizzLevel + 1;
    }

    public void displayWizzLevel() {
        System.out.println("Current level: " + wizzLevel);
    }
}

Yes, that's perfect valid.  In this case, 'wizzLevel' is an instance variable of the class Wizz.  Every copy of Wizz you create has its own wizzLevel, and all methods within Wizz can reference or change it.

The key of course, is to look at the brackets.  Note that 'int wizzLevel' is inside the brackets for the class as a whole, so it's in scope everywhere within the class.

The key takeaway is that when you want to understand where  a variable is available to you, you need to understand that so long as you are still inside the same set of brackets where it was declared you should be good to go.

{
    int outside;
    {
        int inside; //outside is still available
        {
            int wayInside; //inside and outside are still available
        }
        //wayInside is gone
    }
    //inside is gone
}
//outside is gone

Friday, December 5, 2014

Encapsulation - Protecting You From Yourself

Encapsulation sounds like the central plot point of some weird science fiction movie, but actually it's a fundamental technique for improving the reliability and predictability of object oriented programs. Let's pull out our old friend PersonData and see what's ailing him today: 

public class PersonData { 
    public String givenName; 
    public String surName; 
   
    public PersonData() { } 

    public PersonData(String given, String sur) { 
        givenName = given; 
        surName = sur; 
    } 

    public String toString() { 
        return givenName + " " + surName; 
    } 


Let me start by saying that there is nothing fundamentally wrong with this class. It is properly formed, is created with a valid constructor, and has a fully functional toString override method that formats the name is a reasonable manner. Is it object oriented? Well, it's an object at any rate, but we can do better.

 Here's the key issue I'd like to address today. Suppose we had a method that we wanted to use to ensure that a person's name begins with a capital letter. The logic for this is simple enough, but I'm going to deliberately break it for this example, so don't use this method as-is:

public static String ensureFirstCharacterIsUpperCase(String input) { 
    String upperCaseString = null; 
    if (Character.isUpperCase(input.charAt(0))) { 
        return input; 
    } 
    upperCaseString = input.substring(0,1).toUpperCase() + input.substring(1); 
    return input; //Bad programmer! No Pizza! 


 Ignoring for the moment the fact that this method will not quite do what we actually want, how would one go about using it? Well, we could go ahead and write something like this:

PersonData joeBlow = new PersonData(); joeBlow.givenName=ensureFirstCharacterIsUpperCase("joe"); joeBlow.surName=ensureFirstCharacterIsUpperCase("blow"); 
System.out.println(joeBlow); 

That would work just fine, the first, second, and eight hundredth time you do it. But why would you want to? What if you decided that you wanted to capitalize all surnames? What if you wanted to plug in some library that understands how to capitalize special names like MacNeil or something? Do you really want to search out every instance of setting the last name and change it?

There is a better way, my friend, and it gets to one of the other key aspects of object oriented programming. Encapsulation is basically protecting your data from your own programs by making it inaccessible except through a very clearly defined path that you strictly control.

We start by making the fields surName and givenName private. This indicates that they cannot be changed by code in any class except PersonData.

private String givenName; 
private String surName; 

Of course, we aren't quite finished at this point, because we can't change or even see these values. That could make for a remarkably useless class if we did not find a way around it. The way around it is by creating 'accessor' and 'mutator' methods. Those are horrible names so we usually just call them 'getters' and 'setters'. These labels actually make a lot more sense, because the naming convention is to prefix the field name with 'get' and 'set'. 

The required methods for PersonData could look like this:

public void setGivenName(String newGivenName) { 
    givenName = newGivenName; 


public String getGivenName() { 
    return givenName; 


public void setSurName(String newSurName) { 
    surName = newSurName; 


public String getSurName() { 
    return surName; 


 With the fields marked private, and with our getters and setters in place, we would now write the code above more like this:

 PersonData joeBlow = new PersonData(); 
 joeBlow.setGivenName (ensureFirstCharacterIsUpperCase("joe")); 
 joeBlow.setSurName (ensureFirstCharacterIsUpperCase("blow")); 
 System.out.println(joeBlow); 

 But wait, there's more!

 Why should we take a chance that we (or some other developer) fails to use that method to make sure our first character is correct? We can do better than that, and make sure it always happens no matter what kind of night someone had. For now, we'll move 'ensureFirstCharacterIsUpperCase' into PersonData (we'll talk about a better way later) and we'll change our setters a bit:

public void setGivenName(String newGivenName) { 
    givenName = ensureFirstCharacterIsUpperCase(newGivenName); 


public void setSurName(String newSurName) { 
    surName = ensureFirstCharacterIsUpperCase(newSurName); 


 With this done, we can now do this instead:

 PersonData joeBlow = new PersonData(); 
 joeBlow.setGivenName ("joe"); 
 joeBlow.setSurName ("blow"); 
 System.out.println(joeBlow); 

 And still get everything looking the way we expect. We've minimized the amount of code we need to write, and we've encapsulated both field access and a bit of business logic in our PersonData class. Malicious or misinformed programmers will not be able to bypass our hard and fast rules. IDEs won't even let you see the fields in their helpful pop-up dialogs. Dogs will love us.

Of course, we can (and really should) do more than this. First off, we have a constructor that accepts the two names, and we need to make sure it's also performing this task. That's probably most easily done by also having it call the setters. Second, we can think about other business rules we can enforce, like "A user's first name cannot be null or zero length". The setter can check for this and refuse to accept a bad value. Of course, if it does so it also needs to complain to the caller that they've done it wrong. This would be done via an Exception, which we'll need to talk about soon.

Get used to writing your code this way. Protect your data from yourself. Use accessor and mutator methods regularly and uniformly. It's a small amount of extra work, but you will thank yourself later. It's actually a VERY small amount of extra work, given that any decent IDE will create the methods for you if you just ask, and it will certainly save you time and energy later on.

I'll update this post later with a link to a gist containing the fully updated PersonData Object.

Monday, November 17, 2014

Arrays of Golden Sun

We've seen processing of simple integer values already, but what if you have to deal with a bunch of them?  Perhaps you have 20 test results and want to do something with them.

I suppose we could write something like this:

int testResult1;
int testResult2;
int testResult3;
...

Then we could write a calculateAverage function...

int calculateAverage(int testResult1, int testResult2, int testResult3..

You know, I'm already tired of typing that, and I've got a whole lot more to go.  And you just know that next year there will be 22 tests, right?

Never fear, we aren't stuck with such awfulness.  Java (as with most languages) supports the concept of arrays.  Don't fear the word, the concept is actually pretty simple to grasp.

First, let's go back and deal with testResult1.  We can think of that variable as being a box that holds a number.  We can put a number in the box, or we can ask the box what number is in it.

testResult1 = 97;  //We've just put 97 into the box

System.out.println("Your first test result was " + testResult1 ); // We've just asked the box what number is in it.

All the operations boil down to one of those.  If we do math, we're just asking what's in the box.  If we reassign the number (like 'testResult1 ++') we're really just asking what's inside, making a new number and putting the new one into the box.  Whatever was in the box before is gone once you do this, there's no room for two numbers.  These are pretty simplistic boxes.

So, I can conceive of 'testResult1' through 'testResult20' as being a row of 20 boxes, each of which I can use to store or retrieve a number.  But man, it's going to be annoying to do much useful work with individually addressable variables like that.

Enter the array.

Let's just take that same row of 20 boxes and relabel them.  In fact, let's glue them together in a long line and give the whole spiel one single label.  We'll call it 'testResults'.

Of course, testResults is not an int.  It's a grouping of 20 ints.  That's going to make it slightly more difficult to do math on it.  Enter the square bracket and the array index.

If we want to refer to the item in the first box, first we have to get over a little hump.  For reasons we do not really need to get into now, just trust me that they're valid, the first box is number 0, not 1.  So, what we previously would have called 'testResult1' can now be called 'testResults[0]'.  It is important to understand that 'testResults' is NOT an integer.  However, testResults[0] (or testResults[13]) IS an integer and is just a marker for one of the boxes in our row.

I know, that seems a bit more difficult at first, but it turns out not to be.  Here's why:

Remember before?  We had to declare testResult1, testResult2, etc. on individual lines?

Well now we can just do:

int [] testResults = new int [ 20 ];

We've specified that testResults is not an int, but an array of ints with the '[]' notation.  We've made it have 20 boxes with 'new int [ 20 ]'.  (This can be done live at runtime, you could do 'new int [ someCalculatedValue ]').  In one fell swoop we've made storage space for 20 individual (but related) integer values.  It gets better.

The 'calculateAverage' function can now be declared like this:

int calculateAverage( int [] valuesToAverage ) {

Well isn't that a whole lot easier?  And you can imagine that before, that calculateAverage method would have had to look something like this:

return (value1 + value2 + value3 + ... + value20) / 20;

Which seems like it takes up a lot of valuable real estate on screen, and, as mentioned before, is irritating to change.

Our new version takes advantage of the fact that the array is indexed (it could do more but I'll talk about that later):

float total = 0;

for (int i = 0; i < 20; i ++ ) {
    total = total + valuesToAverage[i];
}
return total / 20f;

That's the whole thing.  I didn't even get tired.

Of course, this can be improved further.  What if there aren't 20 values in the array?  What if there are 12?  We could change the code, or we could let the array tell us how big it is:

float total = 0;
float valueCount = valuesToAverage.length;

for (int i = 0; i < valueCount; i++ ) {
    total = total + valuesToAverage[i];
}
return total/valueCount;

Now we have a completely generic method for averaging any number of integer values we want, that we will never have to change again.  All we need to do is make sure before using it that the array we're passing in is sized correctly and populated.  We can stash that into a utility class somewhere and use it for years.

Naturally none of this is going to work without stashing numbers in the array in the first place.

One can initialize an array with hard coded values:

int [] testScores = { 100, 95, 22, 84 };

Or one can write code to set the values.  Assuming we have appropriate helper functions in place, this kind of thing could work.  It's more likely that you'd be getting input from the user or a file for your early experiments with the language.  I think we'll talk about those soon.

int [] testScores = new int[ getNumberOfScores() ];
for ( int i = 0; i < getNumberOfScores(); i++ ) {
    testScores[i] = getScore(i);
}

Of course, that's just the tip of the array iceberg, but I think it gets across the main points:

Arrays:

  1. Are just ordered, indexed lists of the data types we already understand
  2. Can be passed as single labels but all the internal values are readily available
  3. Contain 'meta' information about their contents, particularly how many items they hold
  4. Can make many data processing tasks easier to code and understand
If you're having trouble with this concept, please let me know.  It's good to have a firm grounding in basic aggregate data structures like this before we move on to more complex topics.  Much of what we do in programming involves understanding some concept, then not using it directly, but instead using higher level structures that are better handled if you know what's going on underneath.

View Code

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.

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.

Going Loopy a While

Another key thing you need to understand is looping.  Repeatedly performing identical operations is extremely common in any programming language, and Java supports a pretty full set of looping structures.

Perhaps the simplest loop to understand is the while loop.  Let's write a simple one:

boolean keepRunning = true;

while ( keepRunning )  {
    System.out.println("I am in a loop.");
    keepRunning = false;
}
System.out.println("I am no longer in a loop.");

Now, the above code was the most pointless of all possible while loops, since it executes its code just once and stops.  Specifically:

First, we created a boolean variable and set it equal to true.  We are using this as a flag or condition for the loop.

Then we created a loop, which will execute over and over again so long as keepRunning is still true.  The while statement always expects a boolean expression in the parentheses, and executes one statement so long as that expression evaluates to true.  Curly braces along with any code inside of them count as one statement, and I strongly urge you not to skip them just because some looping or conditional structure you're using only has one line.

So the while statement executes, sees that its condition is true, so it enters the loop.

The system generates the following unexpectedly exciting output to the console:

I am in a loop.

And then it sets keepRunning to false.  The first iteration of the loop is now finished, as we hit the closing brace.

Now the program flow goes back up to the while statement.  keepRunning is now false, so the while statement will bypass the next statement (which, as I mentioned, is everything within the curly braces).

So now we pass control out of the loop and generate the following even more interesting output:

I am no longer in a loop.

That's a lot of words to describe something that is conceptually very simple, which is basically true of many programming structures.  We create instructions and that computer really has to scurry along doing a lot of different stuff for us.  Ah, the power!

Of course, a loop that doesn't loop hardly qualifies for the name, so let's do something just a bit more complex:

boolean keepRunning = true;
int runCount = 0;

while ( keepRunning ) {
    System.out.println("I am in a loop.");
    runCount = runCount + 1;
    if ( runCount > 4 )  {
        keepRunning = false;
    }
}

Try to predict what will happen here.  Follow it through, it's not really that complicated.  I'll wait.






OK, there's not going to be a quiz, I'll just show the output:

I am in a loop.
I am in a loop.
I am in a loop.
I am in a loop.
I am in a loop.

Do you understand what happened here?  If so, you can skip the next bit.


We started off with two variables, keepRunning and runCount.  Let's examine the status of these during each iteration of the loop.

keepRunningrunCountWhat does loop do?
true0Prints I am in a loop.Increase runCount to 1
true1Prints I am in a loop.Increase runCount to 2
true2Prints I am in a loop.Increase runCount to 3
true3Prints I am in a loop.Increase runCount to 4
true4Prints I am in a loop.Increase runCount to 5 then sets keepRunning to false
false5Nothing! We never execute at this point, having failed the while condition

Make sure you understand the flow of that loop completely.  When it makes perfect sense to you, and you understand why everything is happening, you're ready to move on.  to the next section

I wrote that loop in pretty much the longest possible way, because I wanted the flow to be explicitly laid out and easy to follow.  Structures such as boolean flags and counters do get used, but it's rare to have two of them for a job this simple.  Most good programmers try to keep their code terse and tight, without extra fluff.  In this case, we have fluff.

If I were to write the above for myself, and I absolutely had to use a while loop to do it, I'd certainly make use of the following shortcuts:


  1. The '++' operator.  This increments a value.  There's also a similar '--' operator.  I could replace 'runCount = runCount + 1' with 'runCount ++'.  My fingers will thank me, as will those reviewing the code and really expecting to see that.  Just a caveat, the increment operator can appear before OR after the variable, and if it's alone on a line it does not matter how you use it.  But if you are using it in a larger expression it matters.  If you use it as a prefix operator by putting it before the variable, the variable is incremented and then it is evaluated.  If you put it after, the variable is evaluated and then it is incremented.  SO:

    If you write:

    int i = 5;
    int product = ++i * 5;

    Then product will be 30, because it would turn to 6 before being multiplied.

    Whereas if you write:

    int i = 5;
    int product = i++ * 5;

    Then product will be 25, because it would still be 5 when multiplied.

    In either case, after the second line i will have the value 6.
  2. I would take advantage of the boolean nature of comparison operators.  In other words, I can use the value of:

    runCount > 5

    anywhere I need a conditional.  In short, I don't need 'keepRunning' at all.
Instead, I could write my loop this way:

int runCount = 0;

while ( runCount < 5 ) {
    System.out.println("I am in a loop.");
    runCount ++;
}

This is cleaner, shorter, and quite clear once you understand all the bits and pieces.  Indeed, it may be clearer, as there's less to track, and the exit condition of the loop is explicitly stated right where it's used.


You have no doubt noticed by now that I have been starting everything at 0, not 1, which may feel a bit strange.  This is just something you will have to get used to, as it is extremely common for developers to do things that way.  This is most likely due to the way arrays (and pointers in some languages) function, where the first element is zero.  We'll talk about arrays in another post.

Naturally, we sometimes get the counters a bit wrong, perhaps we compared against the wrong value, or used an equals check when we should have used a less than check.  Most of the time, we get this wrong by one.  Always check your logic and indexes thoroughly, particularly before it feels really natural to you.  We call these off-by-one errors fencepost errors.  The reason for this comes down to this:  Imagine you go to your local Home Labyrinth store because you want to put up a hundred feet of fence.  The fence panels are 10 feet wide and you need 10 of them.  You also need posts to go between each panel, and because you haven't had your coffee yet (they open early and you're feeling ambitious this Saturday) you also buy 10 posts.  Everything is going great until you reach the end and realize you need an eleventh post at the far end.  (Usually this happens three minutes after the store closes, in my experience).

There are several other loop structures as well, which I'll discuss next time around.  I want you to get this simplest one locked down firmly before we move on.  It would be possible to only use this one kind of loop and write almost any program, but some of the others are better suited to certain tasks.

View code here

Thursday, November 13, 2014

Variables and How To Use 'em

We've touched upon variables here and there in the previous few posts, and it occurred to me that I should probably clarify their purpose and use.

Programs would be remarkably useless if all you could do was hard code actual values into them.  So what we do is use symbolic representations of numbers, characters, words, etc.  This is similar to algebra, in that we often use 'x', 'y' and other such letters to represent numbers.  They act like placeholders.  Maybe it's better to think of a variable as a shoe box.  You can keep something in the box, and put a label on the box, too.

Let's start off with some very basic examples:

int one = 1;

No, you probably won't use 'one' as a variable name very often, but it's valid Java to do so.  We've created a label called "one" and assigned it the numeric value 1 in one fell swoop (or swell foop, if you prefer).  So we have a shoe box, with a label on it that says "one", and that has the number 1 inside of it.

Now here's why 'one' is a bad variable name:

one = one + 1;

Now one is equal to 2, and we've got the beginning of a comedy routine.

We can perform all kinds of basic math operations on integer variables this same way.

Multiplication:
one = one * 2;

Division:
one = one / 2;

Subtraction:
one = one - 1;

Assuming that all five lines of code above were run in a program, what would one now equal?

Well, it started out as 1, then we added 1 so it became 2.  Then we multiplied by 2 to get 4, divided by 2 to get 2, and then subtracted 1 to get back to 1.

Following chained sequences of events is an important skill for the programmer.  You need to be able to understand what each line of code will do to each variable and keep track of these things as you essentially simulate the program's run in your mind.  This can get very involved, and there's no shame in writing down the state of each variable after each step in a table format.

Of course, 'int' is just one data type, and a limited one at that.  It can't represent decimals easily for instance, and it's fairly hopeless at representing a word processing document.  But it's a start.  I don't intend to provide a complete reference to all data types here, but some basic examples include:

int - Represents an integer (whole number). Examples include 5, 18 and 42
double - Represents a double precision decimal number.  5.1842 could be a double
boolean - Represents a true or false value, which is really useful for conditionals and loops.  Must be either true or false

All of these types share the distinction that they are actual basic data types (atomic types), not objects.  There are objects in the Java library which can be used (fairly interchangeably) in their places.  The equivalent object representations for int, double and boolean are Integer, Double and Boolean.  We'll discuss those in another post, but for now I just want to point out that as a general rule (and you should follow it) object types will begin with an upper case letter, and that will help you to know what you're dealing with.  Of course, over time you'll get very used to the limited menu of atomic types and recognize them quickly.

 There are many mathematical operations one can perform with these data types, some to change them, some to test them.  We addressed some basic arithmetic operators above.

Sometimes you need to test variables for their values.  You can determine equality, or which number is greater by using comparison operators.  The first comparison operator you probably want to know about is equality.  We use a double equal sign for this (==).  This must not be confused with the assignment operator (=)!  Many logical errors in programs have cropped up from confusing these two, and they can sometimes be hard to find.  When quickly scanning through a couple of pages of code, the difference between:

if (n = 5)

and

if (n == 5)

can be hard to spot.  A trick that works surprisingly well for some developers is turning this around.  Basically, "if (5 == n)" is precisely equivalent to "if (n == 5)", but writing "if (5 = n)" is an error the compiler can catch because you cant assign a variable to a constant, only the other way around.  This is sometimes referred to as Yoda style or Yoda syntax.  Interesting is it not?

Technically, these comparison operators wind up evaluating to boolean values.  So it's perfectly OK to do something like this:

boolean nEquals5 = (5 == n);

We will go into booleans in more depth at another time, but for now I just want to point out that you can combine booleans with AND, OR and NOT operators (&&, ||, !) to evaluate more complex questions.

Hopefully, that's enough to keep you from getting too confused as we get into some examples going forward.  If you have questions, please feel free to post them, and I'll try to answer as quickly as I can.  The areas where people have difficulty are where I want to concentrate.

View code here