Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions

  




 

 

Thinking in Java
Prev Contents / Index Next

switch

The switch is sometimes classified as a selection statement. The switch statement selects from among pieces of code based on the value of an integral expression. Its form is:

switch(integral-selector) {
  case integral-value1 : statement; break; 
  case integral-value2 : statement; break;
  case integral-value3 : statement; break;
  case integral-value4 : statement; break;
  case integral-value5 : statement; break;
  // ...
  default: statement;
}


Integral-selector is an expression that produces an integral value. The switch compares the result of integral-selector to each integral-value. If it finds a match, the corresponding statement (simple or compound) executes. If no match occurs, the default statement executes.

You will notice in the preceding definition that each case ends with a break, which causes execution to jump to the end of the switch body. This is the conventional way to build a switch statement, but the break is optional. If it is missing, the code for the following case statements execute until a break is encountered. Although you don’t usually want this kind of behavior, it can be useful to an experienced programmer. Note that the last statement, following the default, doesn’t have a break because the execution just falls through to where the break would have taken it anyway. You could put a break at the end of the default statement with no harm if you considered it important for style’s sake.

The switch statement is a clean way to implement multiway selection (i.e., selecting from among a number of different execution paths), but it requires a selector that evaluates to an integral value, such as int or char. If you want to use, for example, a string or a floating-point number as a selector, it won’t work in a switch statement. For non-integral types, you must use a series of if statements.

Here’s an example that creates letters randomly and determines whether they’re vowels or consonants:

//: c03:VowelsAndConsonants.java
// Demonstrates the switch statement.
import com.bruceeckel.simpletest.*;

public class VowelsAndConsonants {
  static Test monitor = new Test();
  public static void main(String[] args) {
    for(int i = 0; i < 100; i++) {
      char c = (char)(Math.random() * 26 + 'a');
      System.out.print(c + ": ");
      switch(c) {
        case 'a':
        case 'e':
        case 'i':
        case 'o':
        case 'u': System.out.println("vowel");
                  break;
        case 'y':
        case 'w': System.out.println("Sometimes a vowel");
                  break;
        default:  System.out.println("consonant");
      }
      monitor.expect(new String[] {
        "%% [aeiou]: vowel|[yw]: Sometimes a vowel|" +
          "[^aeiouyw]: consonant"
      }, Test.AT_LEAST);
    }
  }
} ///:~


Since Math.random( ) generates a value between 0 and 1, you need only multiply it by the upper bound of the range of numbers you want to produce (26 for the letters in the alphabet) and add an offset to establish the lower bound.

Although it appears you’re switching on a character here, the switch statement is actually using the integral value of the character. The single-quoted characters in the case statements also produce integral values that are used for comparison.

Notice how the cases can be “stacked” on top of each other to provide multiple matches for a particular piece of code. You should also be aware that it’s essential to put the break statement at the end of a particular case; otherwise, control will simply drop through and continue processing on the next case.

In the regular expression in this expect( ) statement, the ‘|’ is used to indicate three different possibilities. The ‘[]’ encloses a “set” of characters in a regular expression, so the first part says “one of a, e, i, o, or u, followed by a colon and the word ‘vowel’.” The second possibility indicates either y or w and: “Sometimes a vowel.” The set in the third possibility begins with a ‘^’, which means “not any of the characters in this set,” so it indicates anything other than a vowel will match.

Calculation details

The statement:
char c = (char)(Math.random() * 26 + 'a');


deserves a closer look. Math.random( ) produces a double, so the value 26 is converted to a double to perform the multiplication, which also produces a double. This means that ‘a’ must be converted to a double to perform the addition. The double result is turned back into a char with a cast.

What does the cast to char do? That is, if you have the value 29.7 and you cast it to a char, is the resulting value 30 or 29? The answer to this can be seen in this example:

//: c03:CastingNumbers.java
// What happens when you cast a float
// or double to an integral value?
import com.bruceeckel.simpletest.*;

public class CastingNumbers {
  static Test monitor = new Test();
  public static void main(String[] args) {
    double
      above = 0.7,
      below = 0.4;
    System.out.println("above: " + above);
    System.out.println("below: " + below);
    System.out.println("(int)above: " + (int)above);
    System.out.println("(int)below: " + (int)below);
    System.out.println("(char)('a' + above): " +
      (char)('a' + above));
    System.out.println("(char)('a' + below): " +
      (char)('a' + below));
    monitor.expect(new String[] {
      "above: 0.7",
      "below: 0.4",
      "(int)above: 0",
      "(int)below: 0",
      "(char)('a' + above): a",
      "(char)('a' + below): a"
    });
  }
} ///:~


So the answer is that casting from a float or double to an integral value always truncates the number.

A second question concerns Math.random( ). Does it produce a value from zero to one, inclusive or exclusive of the value ‘1’? In math lingo, is it (0,1), or [0,1], or (0,1] or [0,1)? (The square bracket means “includes,” whereas the parenthesis means “doesn’t include.”) Again, a test program might provide the answer:

//: c03:RandomBounds.java
// Does Math.random() produce 0.0 and 1.0?
// {RunByHand}

public class RandomBounds {
  static void usage() {
    System.out.println("Usage: \n\t" +
      "RandomBounds lower\n\tRandomBounds upper");
    System.exit(1);
  }
  public static void main(String[] args) {
    if(args.length != 1) usage();
    if(args[0].equals("lower")) {
      while(Math.random() != 0.0)
        ; // Keep trying
      System.out.println("Produced 0.0!");
    }
    else if(args[0].equals("upper")) {
      while(Math.random() != 1.0)
        ; // Keep trying
      System.out.println("Produced 1.0!");
    }
    else
      usage();
  }
} ///:~


To run the program, you type a command line of either:

java RandomBounds lower


or

java RandomBounds upper


In both cases you are forced to break out of the program manually, so it would appear that Math.random( ) never produces either 0.0 or 1.0. But this is where such an experiment can be deceiving. If you consider[18] that there are about 262 different double fractions between 0 and 1, the likelihood of reaching any one value experimentally might exceed the lifetime of one computer, or even one experimenter. It turns out that 0.0 is included in the output of Math.random( ). Or, in math lingo, it is [0,1).
Thinking in Java
Prev Contents / Index Next


 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire