One data type that we haven't spent much time talking about is the poor, neglected boolean. One of the reasons for this is that we haven't had too much use for such a type, but that's about to change.
As we know, a variable of the type boolean can take on only two values: true and false. This doesn't give very many possibilities compared to the type int, for example, which can take on billions of values. (remember that the mathematically speaking, there are an infinite number of integers. However, a computer is finite -- it can't represent all the elements of an infinite set. So the maximum value of an int which is used in a computer is the mathematical set of integers, but 'cut off' at some very high value and some very low value: plus/minus 2 billion, roughly) As a result, we can write down in a table explicitly how operators act on booleans. To do so for an integer would mean writing down every pair of integers and their sum, for example, which would be roughly 2 billion X 2 billion entries. Not practical. Instead, we have an algorithm, or 'method' (roughly speaking) which takes two values of type int and 'figures out' the result.
But we can write a table of results for the results of operations on values of type boolean, and if you look on p. 145 of Nino and Hosch, you'll see such a table for the operators && and ||. These operators are called the logical and and logical or operators respectively. And now you see what the type boolean is supposed to represent: logical values. And boolean expressions are supposed to model logical expressions.
The logical and operator is exactly what you expect:a && b is true only when a is true and b is true. Similarly the logical or operator is hopefully what you expect: a || b is true when a is true or b is true (or both are true).
Since relational expressions give a result of type boolean, we can join together relational expressions using boolean operators. For example,
i > j || 5 < 3 && p != 5 is a valid boolean expression, since each of the relational operations gives a boolean result, and the those boolean results are operated on using the boolean operators to give more boolean results.
One more boolean operator is the ! operator. It is called a unary operator because it only needs one boolean value (kind of like a method
with one parameter) as opposed to &&, || which are binary boolean operators, requiring two boolean values. (like a method with one
parameter). Of course, binary and unary operators aren't just for booleans; the familiar *,+,-,
are binary operators for the type int since they
require two values of type int and return a value of type int. A unary operator for the type int is the - operator, for example, which
negates a value of type int. Notice that the - operator does two separate things here: it acts as a binary operator (does subtraction) and as
a unary operator (negation). This is a feature that we've seen before -- the same operator or method can do different things depending on the
context in which it's used. The + operator is such an example: recall that it concatenates strings, and is the integer addition operator. The equals()
method is similar in this sense: every type can have its own (necessarily different) equals() method. This business of getting some method name
or operator symbol to do more than one thing is called overloading.