Session 4: Class variables and if statements

Class variables (Sections 7.5 and 2.9)
    Global variables
    Constants
if statement (Sections 4.3 and 4.4)
    Simple if statement
    else clause
    Cascaded if statements
    The ambiguous else
Quiz 0

Class variables

Textbook: Sections 7.5 and 2.9

Global variables

Recall Java's scoping rule for variables: The variable is accessible everywhere within the set of braces where it was declared. This means that any variables declared within a particular method aren't available in other methods.

But what if you want a variable to be shared across methods? Such a beast would be called a global variable, since it's available globally. (This contrasts it to the variables declared within methods, which are called local variables.)

Java's class variable construct allows you to create global variables. To declare a class variable, you declare it on the same level where you put the methods, using the words public static.

import csbsju.cs160.*;

public class MinMax {
    public static int min; // notice the addition of the words
    public static int max; // ``public static!''

    // and so on
With these class variable definitions, all the methods in the MinMax class can access the class variables min and max.

As an example where you might want to use this (though the example is quite contrived...) suppose you want to write a method to find both the minimum and the maximum of two numbers. The problem is that a method can return only a single value, and we want to return two values. We can accomplish this by using the class variables to hold the values.

import csbsju.cs160.*;

public class MinMax {
    public static int min;
    public static int max;

    public static void findMinMax(int a, int b) {
        if(a < b) {
            min = a;
            max = b;
        } else {
            min = b;
            max = a;
        }
    }

    public static void run() {
        int input1 = IO.readInt();
        int input2 = IO.readInt();
        findMinMax(input1, input2);
        IO.print("min: "); IO.println(min);
        IO.print("max: "); IO.println(max);
    }
}
This example is a little silly, since we might as well write separate min() and max() methods (or, even better, use the Math.min() and Math.max() methods already included with Java). But you can imagine we might have some more complex computation that ends up modifying several values.

Note: Global variables are considered very poor form, and they should be avoided at almost all costs. The reason is that they hinder the understandability of the program considerably: Say somebody (like your professor, or your boss) opens up your program to try to figure out how it works. The first thing they'll have to do is figure out how the global variables work. Since global variables can change anywhere, the person will have to review the entire program to figure it out.

Generally, you should avoid them through the use of parameters and return values wherever possible. By the end of this class, we'll have seen enough Java that we'll be able to avoid them consistently. In practice, I've written tens of thousands of lines of Java code, and I would be able to count the number of global variables I've used on a single hand. They're just not a good idea; experienced programmers know this, and avoid them assiduously.

Constants

Sometimes you have a constant value you want to refer to, that you know the program will never change. These are constants, and Java provides a way to designate a class variable as a constant using the final keyword. You could place the following among your member definitions.

public static final int FEET_PER_MILE = 5280;
You know the number of feet in a mile isn't going to change while the program is running, so you might as well declare it to be final. (The standard convention for naming constants in Java is to use all capital letters, as here.)

Here's a complete program that uses this.

import csbsju.cs160.*;

public class Convert {
    public static final int FEET_PER_MILE = 5280;

    public static void compute(double feet) {
        IO.println(feet / FEET_PER_MILE);
    }
}

Experienced programmers consider regular, non-final class variables as things to avoid, but they consider constants to be very good for esveral reasons.

And if you're going to name the constant, you might as well add the final keyword, to make it clear to a reader that it's not changing. This tells the compiler to prevent anybody from attempting to change the value.

Java has several built-in constants. For example, Math.PI represents the value of pi (3.14159...).

if statement

Textbook: Sections 4.3 and 4.4

Simple if statement

Let's say you have something that you only want to do in some cases. For example: Your program is to flip a coin. If it comes up heads, it should print ``heads''. You don't always want to print ``heads;'' you just want to print it in the situation where you flip heads.

You accomplish this in Java using the if statement.

if(Math.random() < 0.5) IO.println("heads");
This fragment generates a random value between 0.0 and 1.0; if the random value is below 0.5, then it prints ``heads.''

The syntax for if is very similar to the syntax for while. Like the while statement, you can group several statements together using braces.

if(Math.random() < 0.5) {
    IO.println("heads");
    ++heads;
}

else clause

Often you want to do one thing if something happens and another if that thing doesn't happen. Java accomplishes this using the else construct.

if(Math.random() < 0.5) IO.println("heads");
else IO.println("tails");
This will print either ``heads'' or ``tails,'' depending on whether Math.random() returns between 0.0 and 0.5 or between 0.5 and 1.0.

Again, you can use braces to group statements together in the if clause or the else clause.

if(Math.random() < 0.5) {
    IO.println("heads");
    ++heads;
} else IO.println("tails");
Or you can use braces for both clauses.
if(Math.random() < 0.5) {
    IO.println("heads");
    ++heads;
} else {
    IO.println("tails");
    ++tails;
}

So here's a complete program to flip 100 coins and say how many are heads and how many are tails.

import csbsju.cs160.*;

public class FlipMany {
    public static void run() {
        int i = 0;
        int heads = 0;
        int tails = 0;
        while(i < 100) {
            if(Math.random() < 0.5) ++heads;
            else ++tails;
            ++i;
        }
        IO.print(heads);
        IO.println(" heads");
        IO.print(tails);
        IO.println(" tails");
    }
}

Cascaded if statements

Often you have more than two cases to check. The solution is simple: You put an if statement into the else clause.

if(grade >= 90)
    IO.println("A");
else
    if(grade >= 80)
        IO.println("B");
    else
        if(grade >= 70)
            IO.println("C");
        else
            IO.println("bad");
That's the way you do it in Java, and it's called a cascaded if statement.

But a cascaded if statement looks ugly when it's formatted this way: you end up indenting your lines pretty far. Since this situation occurs often, people instead adopt the following formatting convention where all the elses go on the same indentation level.

if(grade >= 90)
    IO.println("A");
else if(grade >= 80)
    IO.println("B");
else if(grade >= 70)
    IO.println("C");
else
    IO.println("bad");
This style is much prettier and more compact.

If each case has several statements to it, you end up with the following.

if(grade >= 90) {
    IO.println("A");
    gpa = 4;
} else if(grade >= 80) {
    IO.println("B");
    gpa = 3;
} else if(grade >= 70) {
    IO.println("C");
    gpa = 2;
} else {
    IO.println("bad");
    gpa = 0;
}

The ambiguous else

Consider the following program.

if(i * i <= n)
    if(n % i == 0)
        IO.print("no");
  else
      IO.print("yes");
This is ambiguous: Does the else go with the first if or the second if?

Java specifies that the else always goes with the innermost if that it can match. So the Java compiler would treat the above just as it would treat the below.

if(i * i <= n) {
    if(n % i == 0)
        IO.print("no");
    else
        IO.print("yes");
}

Quiz 0