From blocks to methods

Figure 169. Two blocks, same logic Slide presentation
final int agePeter = 26,
          ageCarmen = 30;

final int maxAge;
{
   if (agePeter > ageCarmen) {     
      maxAge = agePeter;
   } else {
      maxAge = ageCarmen;
   }
}
...
...
final int heightDenali = 6910,
          heightCerroTorre = 3128;

final int maxHeight;
{ // Exact same logic as before
   if (heightDenali > heightCerroTorre) {     
      maxHeight = heightDenali;
   } else {
      maxHeight = heightCerroTorre;
   }
}

Figure 170. Replacing two blocks by one method Slide presentation
void main() {
    final int agePeter = 26, ageCarmen = 30;
    final int maxAge = max(agePeter, ageCarmen);

    final int heightDenali = 6910, heightCerroTorre = 3128;
    final int maxHeight = max(heightDenali, heightCerroTorre);
}

// Method replacing blocks
//
int max (int a, int b) {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

exercise No. 66

Computing the absolute value

Q:

Implement a method int abs(int value){...} to compute an expression's absolute value to be used like e.g.:

Code
IO.println(abs(-10));
IO.println(abs(8)); 
Result
10
8

A:

int abs (int value) {
    if (value > 0) {
        return value;
    } else {
        return -value;
    }
}

exercise No. 67

Absolute value, flawed implementation

Q:

We consider an alternate solution of Computing the absolute value :

int abs (int value) {
    if (value > 0) {
        return value;
    } else if (value < 0){
        return -value;
    }
}

This yields a compile time Missing return statement error. What's wrong here? Provide a solution differing from Computing the absolute value .

A:

The abs(int value) {...} must return a value for arbitrary values. This is not the case for value == 0. But even the following code is prone to the very same error message:

int abs (int value) {
    if (value > 0) {
        return value;
    } else if (value < 0){
        return -value;
    } else if( value == 0) {
        return 0;
    }
}

Reason: A Java compiler is simply not clever enough to realize, that indeed all possible values are being handled here. We require an unconditional else {...} clause:

int abs (int value) {
   if (value > 0) {
       return value;
   } else if (value < 0){
       return -value;
   } else { // value == 0
       return 0;
   }
}

This is actually a minor regression in comparison to Computing the absolute value : In case of value == 0 we now require two comparisons rather than one.

exercise No. 68

Arithmetic mean

Q:

Implement a method computing the arithmetic mean of two values:

/**
 * Compute the arithmetic mean of two values.
 *
 * @param a first value
 * @param b second value
 *
 * @return The arithmetic mean of both values.
 */
double getMeanValue(int a, int b) {
    ... // to be implemented
}

Usage example:

Code Result
IO.println(getMeanValue(1, 3));
IO.println(getMeanValue(1, 2));       
2.0
1.5

A:

The following naïve approach does not work:

double getMeanValue(int a, int b) {
    return (a + b) / 2;
}

Executing getMeanValue(1, 2) yields 1.0 rather than 1.5. This is due to fractional digits in the integer 3 / 2 division being cut off as being shown in Dividing values . We require a double operation instead, e.g. by turning the int literal 2 into a double literal 2.0 thereby forcing an int / double division:

double getMeanValue(int a, int b) {
    return (a + b) / 2.0;
}
Figure 171. Passing values to methods Slide presentation
Code Result
void main() {
  int argument = 2;
  int square = getSquare(argument);
  IO.println("Square=" + square);            
  IO.println("Argument=" + argument);
}

/**
 * Compute the square x * x of a value x.
 *
 * @param x Value
 * @return Square of value.
 */
int getSquare(int x) {
  x *= x;
  return x;
}

Square=4
Argument=???

Figure 172. Passing values to methods Slide presentation
void main() {
  int argument = 2;
  int square = getSquare(argument);
  IO.println("Square=" + square);            
  IO.println("Argument=" + argument);           
}

int getSquare(int x) {
  x *= x;
  return x;
}
int argument = 2;
int square;
{
  int x = argument; // argument unchanged          
  x *= x;
  square = x;
}
IO.println("Square=" + square);
IO.println("Argument=" + argument);

Remark: This is a call-by-value method call.


exercise No. 69

Analyzing a method call

Q:

Analyze the call of main(...) to getSquare(...) in Figure 172, “Passing values to methods ”. Set a breakpoint at the line containing int square = getSquare(argument). Then step into getSquare(...). What do you observe?

A:

The variables argument in main(...) and x in getSquare() represent distinct values. On calling getSquare(...) argument is being copied into x.