Chapter X

An Introduction to
Programming and Object
Oriented Design using Java
2nd Edition. May 2004
Jaime Niño
Frederick Hosch
Chapter 4 : Conditionals
Objectives
 After studying this chapter you should understand the
following:
 the notions of preconditions, postconditions, and invariants;
 the purpose of a conditional statement;
 the function of boolean expressions;
 the purpose of a compound statement.
 Also, you should be able to:
 write and evaluate boolean expressions;
 write conditional statements of various forms;
 implementation methods that use conditional statements;
 implement a class tester which automatically verifies test results.
May 2004
NH-Chapter4
1
Postconditions and invariants
Method currentCount in Counter is specified as
/**
* The number of items counted.
*/
public int currentCount () { …
 Specification stipulates invoking method returns a
value of type int.
May 2004
NH-Chapter4
2
Postconditions and invariants
Can be more precise in specifying result : integer result is nonnegative.
/**
* The number of items counted.
*
* @ensure this.currentCount() >= 0
*/
public int currentCount () { …
 Postcondition: condition that implementor promises will be
satisfied when method completes execution.
 Implementor must make sure that the method satisfies the
postcondition.
May 2004
NH-Chapter4
3
Postconditions and invariants
 Need to make sure instance variable used to store
current count will never contain a negative value.
 Document this via a class invariant:
private int count;
// current count
// invariant: count >= 0
A class invariant will always be true of all instances of the
class.
May 2004
NH-Chapter4
4
Postconditions and invariants
 If we add decrementCount to Counter:
public void decrementCount ()
Decrement positive count by 1; zero count remains zero.
 In implementation, need to add guard to be sure not
to decrement when count == 0
May 2004
NH-Chapter4
5
The if-then statement
if (condition)
statement
B E G IN
true
condition
false
statement
E N D
May 2004
NH-Chapter4
6
Implemeting decrementCount
/**
* Decrement positive count by 1;
* zero count remains zero
*/
public void decrementCount () {
if (count > 0)
count = count - 1;
}
May 2004
NH-Chapter4
7
Explorer: invariants and guards
Restrict Explorer’s tolerance to be a non-negative integer.
private int tolerance;
// current tolerance
// invariant: tolerance >= 0
/**
* Damage (hit points) required to defeat
* this Explorer.
*
* @ensure tolerance >= 0
*/
public int tolerance () {
return tolerance;
}
 Need to insure value assigned in each case is not negative.
May 2004
NH-Chapter4
8
Explorer: invariants and guards
 Consider method takeThat.
 Need to guard the two statements:
if (hitStrength <= tolerance)
tolerance = tolerance - hitStrength;
if (hitStrength > tolerance)
tolerance = 0;
But, only one of those should execute when invoking takeThat.
May 2004
NH-Chapter4
9
if-then-else statement
if (condition)
statement1
else
statement2
B E G IN
true
false
condition
statement
statement
2
1
E N D
May 2004
NH-Chapter4
10
Implementing method takeThat
public void takeThat (int hitStrength) {
if (hitStrength <= tolerance)
tolerance = tolerance - hitStrength;
else
tolerance = 0;
}
May 2004
NH-Chapter4
11
Implementing constructor
public Explorer (String name, Room location,
int strength, int tolerance) {
…
if (tolerance >= 0)
this.tolerance = tolerance;
else
this.tolerance = 0;
…
}
May 2004
NH-Chapter4
12
Compound statements
if (condition) {
statement1
…
statementN
}
if (condition) {
statement11
…
statement1N
} else {
statement21
…
statement2M
}
May 2004
NH-Chapter4
13
Conditions: boolean expressions
Boolean expressions:
Produce boolean values when evaluated;
Evaluate to true or false.
Can declare boolean variables, and assign values:
private boolean tooBig;
And can assign values to it:
tooBig = true;
Or
tooBig = size > 10;
May 2004
NH-Chapter4
14
Handling multiple cases
 A conditional statement divides problem into two
cases to be considered independently.
 In many problems, there are more than two cases, or
cases need to be further divided into subcases.
 Use nesting conditional statements.
May 2004
NH-Chapter4
15
Handling multiple cases
 Assume class Date with properties day, month,year.
 Implement a Date’s query that will tell whether or
not a date occurs in a leap year.
public boolean isLeapYear ()
This Date occurs in a leap year.
May 2004
NH-Chapter4
16
Handling multiple cases
isLeapYear
Case: year divisible by 4
???
Case: year not divisible by 4
not a leap year.
Case: divisible by 100 Case: not divisible by
100
???
is leap
Case: divisible Case: not divisible
by 400
by 400
is leap
is not leap
May 2004
NH-Chapter4
17
Handling multiple cases
// This Date occurs in a leap year.
public boolean isLeapYear () {
boolean aLeapYear;
if (year % 4 == 0)
if (year % 100 == 0)
// if divisible by 100,
// must also be divisible by 400
aLeapYear = (year % 400 == 0);
else // divisible by 4, not by 100
aLeapYear = true;
else // not divisible by 4
aLeapYear = false;
return aLeapYear;
}
May 2004
NH-Chapter4
18
Cascading conditionals
 When problem splits into more than two cases:
 “cascade” if-then-else statements.
if (case1)
handleCase1
else if (case2)
handleCase2
…
else if (penultimateCase)
handlePenultimateCase
else
handleLastCase
May 2004
NH-Chapter4
19
TrafficLight’s change() method
change
:
case: light is GREEN
change to YELLOW
May 2004
case: light is YELLOW
change to RED
NH-Chapter4
case: light is RED
change to GREEN
20
TrafficLight’s change() method
public void change () {
if (light == GREEN)
light = YELLOW;
else if (light == YELLOW)
light = RED;
else // light == RED
light = GREEN;
}
May 2004
NH-Chapter4
21
Dangling else
There is an ambiguity as to whether the structure
if (condition1)
if (condition2)
statement1
else
statement2
 Is it an if-then nested in an if-then-else, or an
if-then-else nested in an if-then?
May 2004
NH-Chapter4
22
Dangling else
B E GIN
false
condition1
B E GI N
true
condition1
true
false
condition2
statement2
true
false
statement1
statement2
condition2
true
statement1
false
E ND
May 2004
E ND
NH-Chapter4
23
Dangling else: equivalent statements
if (condition1)
if (condition2)
statement1
else
statement2
May 2004
if (condition1) {
if (condition2)
statement1
else
statement2
}
NH-Chapter4
24
Example: combination lock
 Responsibilities:
 Know:
The combination
whether unlocked or locked
 Do:
lock
unlock
May 2004
NH-Chapter4
25
CombinationLock class
 Class: CombinationLock
 Queries:
 is open
 Commands:
 lock
 unlock
May 2004
NH-Chapter4
26
Class CombinationLock specifications
public class CombinationLock
Contructor:
public CombinationLock (int combination)
Queries:
public boolean isOpen()
Commands:
public void close ()
public void open(int combination)
May 2004
NH-Chapter4
27
Class CombinationLock
implementation
Component variables:
private int combination;
private boolean isOpen;
May 2004
NH-Chapter4
28
Structure for a simple test
public class CombinationLock {
private int combination;
private boolean isOpen;
public CombinationLock (int combination) {
}
public boolean isOpen () {
return true;
}
public void close () {
}
public void open (int combinationToTry) {
}
}
May 2004
NH-Chapter4
29
Structure for a simple test
class CombinationLockTest {
private CombinationLock lock;
public CombinationLockTest () {
}
public void runTest () {
}
}
public class TestCombinationLock {
public static void main (String[] argv) {
(new CombinationLockTest()).runTest();
}
}
May 2004
NH-Chapter4
30
Precondition
 A condition client of a method must make sure holds
when method is invoked.
 “Require”s : Constructor and method enter have
requirements that clients must meet for them to
execute properly.
May 2004
NH-Chapter4
31
Constructor specifications
/**
* Create a lock with the specified
combination.
*
* @require:
*
0 <= combination && combination <= 999
* @ensure:
*
this.isOpen()
*/
public CombinationLock (int combination) …
May 2004
NH-Chapter4
32
Testing locks
Need method to create and test lock with given combination:
private void testLock (int combination)
Test a lock with the specified combination.
 Invoke this method in runTest for each lock to
test.
public void runTest () {
testLock(0);
testLock(123);
testLock(999);
}
May 2004
NH-Chapter4
33
Automating checking of test results
private void verify (boolean test, String message) {
if (!test)
System.out.println(
"Verification failed: " + message);
}
May 2004
NH-Chapter4
34
testLock method
 testLock method must create lock and run initial
state test:
private void testLock (int combination) {
lock = new CombinationLock(combination);
testInitialState();
}
May 2004
NH-Chapter4
35
testLock method
Initial state test should make sure that lock is open.
So, instead of writing the test method:
private void testInitialState() {
System.out.println("Initial state: " +
lock.isOpen());
}
 Write:
private void testInitialState() {
verify(lock.isOpen(), "initial state");
}
May 2004
NH-Chapter4
36
Class CombinationLock implementation
 The straightforward implementations:
public CombinationLock (int combination) {
this.combination = combination;
this.isOpen = true;
}
public boolean isOpen () {
return isOpen;
}
May 2004
NH-Chapter4
37
Class CombinationLock implementation
 In constructor, there are two variables with same name.
 Component variable and
 local variable combination.
 this.combination refers to component variable.
 If variable does not include object reference this in front
of it, it is a reference to local variable.
May 2004
NH-Chapter4
38
Class CombinationLock
implementation
May 2004
NH-Chapter4
39
Method to test close
write method to test close, and invoke it
from testLock:
private void testClose() {
lock.close();
verify(!lock.isOpen(), "close open lock");
lock.close();
verify(!lock.isOpen(), "close closed lock");
}
private void testLock (int combination) {
lock = new CombinationLock(combination);
testInitialState();
testClose();
}
May 2004
NH-Chapter4
40
Implementing close in Lock
 Command close is also easy to implement:
public void close () {
isOpen = false;
}
May 2004
NH-Chapter4
41
Method to test open
 Test for the method open: four cases to test:
closed lock, correct combination: lock opens;
open lock, correct combination: lock remains open;
closed lock, incorrect combination: lock remains closed.
open lock, incorrect combination: lock remains open;
 Test depends on combination, so pass correct
combination as argument:
private void testOpen (int combination)
May 2004
NH-Chapter4
42
testOpen method
private void testOpen (int combination) {
int badCombination = (combination + 1) % 1000;
// test with correct combination:
lock.close();
lock.open(combination); // open closed lock
verify(lock.isOpen(), "open closed lock");
lock.open(combination); // open opened lock
verify(lock.isOpen(), "open opened lock");
// test with incorrect combination:
lock.open(badCombination); // try opened lock
verify(lock.isOpen(), "bad comb, opened lock");
lock.close();
lock.open(badCombination); // try closed lock
verify(!lock.isOpen(), "bad comb, closed lock");
}
May 2004
NH-Chapter4
43
testOpen method
 Add an invocation of this method to testLock:
private void testLock (int combination) {
lock = new CombinationLock(combination);
testInitialState();
testClose();
testOpen(combination);
}
May 2004
NH-Chapter4
44
Method open implementation
The following implementation of open fails the tests.
public void open (int combination) {
isOpen = (this.combination == combination)
}
 test will produce the following output:
Verification failed: bad comb, opened lock
Verification failed: bad comb, opened lock
Verification failed: bad comb, opened lock
 Root of problem: attempt to open an already opened
lock with incorrect combination should not close it.
May 2004
NH-Chapter4
45
Method open implementation
 Correct implementation of method uses a conditional
statement that opens the lock if the combination is correct, and
does nothing if the combination is not correct:
public void open (int combinationToTry) {
if (this.combination == combinationToTry)
isOpen = true;
}
May 2004
NH-Chapter4
46
Digit by digit lock
 This lock has a 3 digit combination.
 To open the lock, client provides the digits one at a time.
 If client enters three digits of combination in order, lock
opens.
 It doesn’t matter how many digits client provides, as long as
combination is given.
May 2004
NH-Chapter4
47
Digit by digit lock: combination 123
May 2004
Digit Entered
4
1
2
4
3
1
2
3
Lock Status
closed
closed
closed
closed
closed
closed
closed
open
Digit Entered
1
2
3
4
7
Lock Status
closed
closed
open
open
open
NH-Chapter4
48
Digit by digit lock: combination 123
 if client gives command close when combination has been
partly entered,
Client Command
Lock Status
enter 1
enter 2
close
enter 3
closed
closed
closed
?
Client Command
Lock Status
enter 1
enter 2
close
enter 3
open
open
open
closed
?
 command close resets lock, entire combination must be
entered.
May 2004
NH-Chapter4
49
Digit by digit lock
 If combination is 123 and digits 1-2-2 are entered, we
need three digits to open the lock:
Digit Entered Lock Status
1 closed
2 closed
2 closed
(need 2-3 to open)
(need 3 to open)
(need 1-2-3 to open)
 If combination is 223 and the digits 2-2-2 are
entered, a 3 will still open the lock:
Digit Entered Lock Status
2 closed
2 closed
2 closed
May 2004
(need 2-3 to open)
(need 3 to open)
(still need 3 to open)
NH-Chapter4
50
Class CombinationLock
Constructor:
public CombinationLock (int combination)
require: combination >= 0 && combination <=999
Queries:
public boolean isOpen ()
Commands:
public void close ()
public void enter (int digit)
require: digit >=0 && digit <=9
May 2004
NH-Chapter4
51
CombinationLock responsibilities
 Know:
 the 3-digit combination.
 whether locked or unlocked.
 the last three digits entered.
 Do:
 lock.
 unlock, when given the proper combination.
 accept a digit.
May 2004
NH-Chapter4
52
Getting digits from integers.
 Using % and / operators, can extract each digit.
 Suppose combination 123.
123 % 10 -> 3
123 / 10 -> 12
12 % 10 -> 2
12 / 10 -> 1
 % 10 gets last digit
 / 10 gets remaining digits.
May 2004
NH-Chapter4
53
CombinationLock implementation
private boolean isOpen;
//
private int digit1;
//
private int digit2;
//
private int digit3;
//
// invariant:
// digit1 >= 0 && digit1 <= 9
// digit2 >= 0 && digit2 <= 9
// digit3 >= 0 && digit3 <= 9
May 2004
lock is unlocked
1st combination digit
2nd combination digit
3rd combination digit
&&
&&
NH-Chapter4
54
CombinationLock implementation
// last, secondToLast, thirdToLast are the last three
// digits entered, with last the most recent.
// a value of -1 indicates digit has not been entered.
private int last;
private int secondToLast;
private int thirdToLast;
// invariant:
// -1 <= last <= 9 &&
// -1 <= secondToLast <= 9 &&
// -1 <= thirdToLast <= 9
May 2004
NH-Chapter4
55
 Combination is 223, and digits 2-2 have been entered
to a closed lock
Combinati onLock
May 2004
digit1
2
digit2
2
digit3
3
isO pen
false
t hirdTolast
-1
secondToLast
2
last
2
NH-Chapter4
56
Implementing constructor
public CombinationLock (int combination) {
digit3 = combination % 10;
combination = combination / 10;
digit2 = combination % 10;
digit1 = combination / 10;
isOpen = true;
last = -1;
secondToLast = -1;
thirdToLast = -1
}
May 2004
NH-Chapter4
57
Implementing methods
Query isOpen is the same as before.
public boolean isOpen () {
return isOpen;
}
 Command close must resets lock.
public void close () {
open = false;
last = -1;
secondToLast = -1;
thirdToLast = -1;
}
May 2004
NH-Chapter4
58
Implementing method enter
public void enter (int digit) {
thirdToLast = secondToLast;
secondToLast = last;
last = digit;
if (thirdToLast == digit1 &&
secondToLast == digit2 && last == digit3)
isOpen = true;
}
May 2004
NH-Chapter4
59
Relational operators
<=
less than or equal
>
>=
==
!=
greater than
greater than or equal
equal (A single ‘=‘ denotes assignment.)
not equal
 A relational expression consists of two expressions
joined with a relational operator.
May 2004
NH-Chapter4
60
Relational expressions
 Let i1=10, i2=-20, i3=30.
i1 < 12
 true
i1 <= 10
 true
i3 == i1
 false
i1 != 2
 true
i1 < 10
 false
i2 > 0
 false
2*i1 == i2+40
 true
i2*(-1) != i1+i1  false
May 2004
NH-Chapter4
61
Relational expressions
 An expression like a<b<c is illegal.
 int values are converted to double, in mixed type
comparisons:
10 > 2.5  10.0 > 2.5  false
May 2004
NH-Chapter4
62
Relational expressions
 floating point values are approximations for real
numbers, avoid using equality or inequality operators
with them.
(1.0/6.0 + 1.0/6.0 + 1.0/6.0 +
1.0/6.0 + 1.0/6.0 + 1.0/6.0) == 1.0  false
May 2004
NH-Chapter4
63
Reference equality and object
equality
 Operators == and != can be used to compare values
of any type.
 Comparing reference values must be of same type.
Counter counter1;
Counter counter2;
Explorer myHero;
counter1 == counter2 // legal
counter1 == myHero
May 2004
// compilation error
NH-Chapter4
64
Reference equality and object
equality
Two reference values are equal if they refer to same object.
How to check if two different objects are equal?
if string1, string2, and string3 are String variables,
string1 = "c";
string2 = "ab" + string1;
string3 = "a" + "bc";
string2 and string3 will reference two distinct objects.
string2 == string3
 false
 use String method equals,
string2.equals(string3)
May 2004
 true
NH-Chapter4
65
Boolean operators
!
&&
||
not
and
or
Use :
! booleanExpression
booleanExpression && booleanExpression
booleanExpression || booleanExpression
A boolean expression evaluates to true or false
May 2004
NH-Chapter4
66
The ! (not) operator
“Not” reverses boolean values.
!true  false
!false  true
 Given : i1=10;
!( i1 > 9)  !(true)  false
Beware: “Not” has high precedence.
! i1 > 9  (!i1) > 9  illegal
May 2004
NH-Chapter4
67
&&, || (and then, or else)
operators
Given: i1=10;
(i1>10)||(i1==10)
(i1>10)||(i1<0)
(i1>0)&&(i1<5)
(i1>0)&&(i1<20)
May 2004




NH-Chapter4
false
false
true
true
||
||
&&
&&
true  true
false  false
false  false
true  true
68
&&, || (and then, or else)
operators
 && and || have lower precedence than the relational operators.
 Parentheses are still useful as they enhance readability.
i1 < i2 && i1 < i3 means
(i1 < i2) && (i1 < i3)
 Using the “and then” operator, can express the condition that
value of i1 is between 0 and 20:
(0 < i1) && (i1 < 20)
May 2004
NH-Chapter4
69
The && and || are lazy operators
 They evaluate only the left operand only when that suffices.
 Given i1=10;
(i1 < 10) && (i1 > 0)  false && (i1 > 0) false
(i1 < 11) || (i1 > 100) true || (i1 > 100) true
 Right operands, (i1 > 0) and (i1 > 100), are not evaluated.
 Useful when considering expressions like
(x == 0) || (y/x < 10)
 If left operand is true, x is 0, evaluating right operand will result in an attempt
to divide by 0 and a run-time error.
May 2004
NH-Chapter4
70
Operator precedence
High
unary +, unary -,
*, /, %
+, <, <=, >, >=
==, !=
&&
||
!
Low
May 2004
NH-Chapter4
71
DeMorgan’s Laws
 Useful for simplifying expressions.
!(b1 && b2)  !b1 || !b2
!(b1 || b2)  !b1 && !b2
!(i1>5 && i1<8)  !(i1>5) || !(i1<8)
May 2004
NH-Chapter4
72
Summary
 Introduced boolean expressions and conditional
statements.
 Conditional statements allow us to specify alternative
computations and the circumstances under which
each is to be performed.
 The particular action to be done is determined by the
processor at execution time, depending on the current
data values.
May 2004
NH-Chapter4
73
Summary
The two forms of conditional statement we’ve seen are
if-then and if-then-else.
if (condition)
statement
 With an if-then-else, we specify two possible actions,
one of which will be done:
if (condition)
statement1
else
statement2
May 2004
NH-Chapter4
74
Summary
Syntax of the Java language permits only a single statement as
a conditional alternative.
Need a way to package a number of statements into one.
Compound statement: put braces around a sequence of
statements:
{ statement1 statement2 … statementn }
May 2004
NH-Chapter4
75
Summary
Boolean expression: an expression that evaluates to a
boolean value, true or false.
Several kinds of operators useful for constructing boolean
expressions:
relational operators <, <=, >, and >=,
equality operators == and !=,
boolean operators &&, ||, and !.
May 2004
NH-Chapter4
76
Summary
introduced preconditions, postconditions, and invariants.
Important in the specification and correctness verification of
our designs.
Not part of the language per se, we include them in comments.
May 2004
NH-Chapter4
77
Summary
Client of a method responsible for making sure that all method
preconditions are satisfied before invoking method.
Method will work correctly only if preconditions are satisfied.
Preconditions are documented in a require clause of method
specification.
May 2004
NH-Chapter4
78
Summary
Method implementor is responsible for making sure that all
postconditions are satisfied when method completes.
Postconditions documented in an “ensure clause” of method
specification.
May 2004
NH-Chapter4
79
Summary
Invariants are conditions that always hold.
Class invariants are conditions that are always true of all
instances of a class.
A class instance is a consistent and coherent model of whatever
entity the class represents if class invariants hold.
May 2004
NH-Chapter4
80