RU beehive logo ITEC Department logo
ITEC 120
2007spring
ibarland,
jpittges

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs

lect03b
Nesting if-else; connectives

nesting if-elses

Consider the following, loosely based on this week's lab exercise:

if (salePrice < 25.00) {
  finalValueFee = /* calculate fee for auctions under $25.00 */ ;
  }
else {
  
  if (salePrice < 1000.00) {
    finalValueFee = /* calculate fee for auctions in [$25.00,$1000.00) */ ;
    }
  else {
    finalValueFee = /* calculate fee for auctions in [1000.00,∞) */ ;
    }
  

  }
This whole thing is a perfectly fine if-else statement (once the comments are replaced with actual expressions)! After all, it matches the general syntax for if-else:
if (condition) {
  statements
  }
else {
  statements
  }
Our page of syntax now includes several types of statements: It's worth mentioning specially, that indentation starts becoming extremely important, to people reading your programs: it would be very easy to mislead people about what your program is doing, by being careless about indenting. After all, we had an if-else statement inside of another else clause, but it could conceivably also be written inside the if clause. Curly-brackets tell the computer what contains what else, but indentation is what tells humans how the code is structured. (If your code makes me stop to think about whether its visual structure matches what it really does, you will lose points.)

This idea of nesting an if-else statment inside another else clause is actually very common; it happens whenever we need to choose between more than two equal options. While what we wrote makes sense, it's annoying for two reasons:

In response to these common concerns, Java includes a variant of tghe if-else statement, call the if-else-if statement. Here's an example:
/** Return a greeting, selected randomly from a list of several greetings.
 * @return A greeting (randomly selected, not necessarily uniformly).
 */
String greet() {
  int choice = (new java.util.Random()).nextInt(100);
  // We'll discuss the "new" statement later1; here's the upshot: the local variable 
  // 'choice' now stores a number in the interval [0,99], a.k.a. [0,100).
  
  if (choice < 30) {
    return "Hello.";
    }
  else if (choice < 33) {  
    return "Aloha.";
    }
  else if (choice < 50) {  
    return "Buenos dias, amigo/amiga.";
    }
  else if (choice < 99) {  
    return "Yo.";
    }
  else if (choice < 100) {  
    // Not an advisable greeting.  Use sparingly.
    return "I am a javabot: System dot out dot println open \"hello\" close.";
    }
  else {
    // This line will never be reached.
    // Still, we need to appease the compiler...
  
    }

  }
Some discussions:

Technicalities

  1. you can omit the else, if the curly-brackets would be empty:
      /** Given how many slices of (say) mushroom pizza are
       * currently available, create a nice tempting message
       * to advertise (shout out, or post, or put on a
       * LED sign...)
       * 
       * @param topping The type of pizza (e.g. "pepperoni")
       * @param piecesReady The number of currently ready-to-serve
       *    slices with the given topping.
       * @return A complete sentence describing the inventory.
       * For example:
       * inventoryMessage( "mushroom", 3 ) 
       *   = "There are 3 piping hot pieces of mushroom pizza, ready to eat!"
       */
      String slicesReadyMsg( String topping, int slicesReady ) {
        String verbForm  = "are";   // The correct verb for our result.
        String plurality = "s";  // The noun-suffix, correctly plural or singular.
        
        if (numInStock == 1) {
          verbForm = "is";
          plurality = "";
          }
    
        return   "There " + verbForm + " "
               + slicesReady +
               + " piping hot slices of "
               + topping + ("pizza" + plurality)
               + " in stock.";
        }
    
  2. Moreover, when there is only a single statement in the body, the book reveals that you can conceivably omit the curly-brackets. 3
    optional: The following explanation is optional, and will be skipped in lecture, as long as you read the concluding edict below.)
    Alas, omitting the brackets is bad for several reasons:
    1. It's fairly common that you decide later to go back and add something to the if- or else- case, and you end up adding the brackets later. Moreover, if you have several lines in a block and delete them down to just one, you'd want to delete the brackets to be consistent (and not cause readers to wonder if there is some unintentional bug).
    2. This usually leads to confusion though, and the book has to spend several minutes talking about dangling elses.
    3. Consider:
         if (numInStock == 1)
           verbForm = "is";
         else
           verbForm = "are";
         
      What if we go back, and decide to add the lines for plurality, but we forget to put in curly-braces?:
         if (numInStock == 1)
           verbForm = "is";
           plurality = "";    // DANGER, WILL ROBINSON!
         else
           verbForm = "are";
           plurality = "s";
         
      Java gives an error “else without an if” -- why? If we hadn't had any else statement at all, would we have caught our error?
Edict: Even if you have only one line in an if- or else- block, include curly-braces.
One exception:

boolean connectives: &&, ||, !

The boolean functions are && (“and”) and || (“or”). For instance,

((30 <= choice) && (choice < 33))
reads as “choice is at least thirty, and less than 33”. Similarly,
((newFace < 1) || (newFace > NUM_SIDES))
tests for newFace being less than 1, or bigger than NUM_SIDES.

In general, && looks at the boolean expressions on each side, and the entire && will evaluate to true if (and only if) the left side and the right side evaluate to true:

expr1 expr2 (expr1&&expr2)
false false false
false true false
true false false
true true true
(expr1 and expr2 can be any other boolean expression—including more-deeply-nested and/or expressions!)
Complementing &&, an entire || expression evaluates to true if (and only if) one side or the other evaluates to true:
expr1 expr2 (expr1||expr2)
false false false
false true true
true false true
true true true
Really, you can think of && as a function with the signature boolean &&( boolean b1, boolean b2 ) (although, like arithmetic4, we write them in infix notation, with the function-name coming inbetween its two inputs, rather than in-front-of-them-with-parentheses).

Exercise: What is the value of:

( ((3 <= 7) || (4 == (2+3))) && (Math.sqrt(4) > 0.0) )
This is just like solving an arithmetic problem, except that we are dealing with true and false instead of all the integers5.

It's worth a mention that in English, “or” is used in two different ways: The inclusive-or, which is what || means, means “one or the other or both”. For example, if the question on the tax form asks “are you over 18, or had income of more than $20,000”, and you meet both criteria, then the answer is true. (People might use “and/or” to emphasize they include the “and” part.) However, sometimes English uses “or” to mean one or the other but not both. For instance, “You can eat veal, or you can be morally responsible” is implying that one option precludes the other. (You may or may not agree with that presumption, of course.) Similarly, if you are told “Keep dating your ex, or date me!”, don't presume that the option of both is included in the “or”!

While we're on the topic, there is one last boolean operator, ! (“not”):

expr !expr
false true
true false
So (2+2 == 4) is true, but !(2+2 == 4) is false. This could also have been written directly using the not-equals operator: (2+2 != 4).

Let's revisit mustRegisterForDraft. The current laws are a bit different from what is shown: only men aged 18-25 must register. Update our function accordingly:

/**
 * @param age The age (in years) of the person in question.  E.g., 18months is age 1.
 * @param ___  _______________________________________________
 * @return whether or not the person must register with Selective Service.
 *   mustRegisterForDraft_v2( 0, ___) == false
 *   mustRegisterForDraft_v2(22, ___) == true
 *   mustRegisterForDraft_v2(22, ___) == 
 *   mustRegisterForDraft_v2(__, ___) ==
 *   mustRegisterForDraft_v2(14, ___) == false
 */
boolean mustRegisterForDraft_v2( int age, ____ ______ ) {
  return _ (age >= 18) __  _______ _;
  }
By the way, now we see more clearly, the advantage of making this its own function -- we don't have to update the rules in several places. In fact, we'll need to update our function further, to account for whether the person is a U.S. citizen, or an alien living in the U.S. In fact, ultimately your code should be a direct translation of the actual regulations, which can be fairly detailed.

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


Naming convention: start boolean variable names with a word to make it clear that the variable stores a true/false value: “isHappy”, “hasAllPrereqs”, etc.

Aside: Some languages — not Java — allow “?” to be part of a name; in those languages boolean variables are often named “happy?”, “hasAllPrereqs?”. Since functions which return a boolean value are sometimes called “predicates”, some people use the letter “p” to indicate a predicate function: “isPrimeP(int n)”, “flightIsBookedP( int flightNum )”.


1

Well, new is nothing too magical; it creates a particular instance of a class. In this case, the class isn't “PizzaServer” but “java.util.Random” (a longwinded name, indeed). And instances of this class can't be asked about pizzaArea, but they do know how to generate a nextInt randomly.

So far we have been making new instances in BlueJ by right-clicking on “new PizzaServer()” (or whatever our class is named), but “new” is actual Java code to do the same thing. Note that we could have even named this java.util.Random instance with a local variable, if we had wanted to:

    java.util.Random ro = new java.util.Random();
    int choice = ro.nextInt(100);
    
We'll talk more about new and local-variables-to-hold-instances in the following weeks, but all the fundamental concepts are in place!

     

2 So we could actually use a series of if statements, rather than a big if-else.      

3So really, the actual syntax for Java's if-else statement is

if (statement)
  expression
else
  expression
This is actually a general case of the version-with-brackets, given in these notes. Why? Because along with assignment statments and return statements and if statements, there is a block statement, which looks like { statements… }.      

4Just like we think of + and * as functions which take in two numbers, and return a number.      

5If you look at the tables and squint, thinking of false,true being like 0,1 and ||,&& being like +,* then these tables above really do look fairly similar to arithmetic.      

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


©2007, Ian Barland, Radford University
Last modified 2007.Aug.27 (Mon)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme