know about StreamEndException, this construction can be confusing since it moves the loop termination
from inside the for loop into the surrounding try block.
In some situations no reasonable flag value exists. For example, a class for a stream of double values can
contain any valid double, and there is no possible end-of-stream marker. The most reasonable design is to
add an explicit eof test method that should be called before any read from the stream:
while (!stream.eof())
process(stream.nextDouble());
stream.close();
On the other hand, continuing to read past the end of input is not expected. It means that the program didn't
notice the end and is trying to do something it should never attempt. This is an excellent case for a
ReadPastEndException. Such behavior is outside the expected use of your stream class, and throwing
an exception is the right way to handle it.
Deciding which situations are expected and which are not is a fuzzy area. The point is not to abuse exceptions
as a way to report expected situations.
Exercise 12.2: Decide which way the following conditions should be communicated to the programmer:
- Someone tries to set the capacity of a PassengerVehicle object to a negative value.
- A syntax error is found in a configuration file that an object uses to set its initial state.
A method that searches for a programmer-specified word in a string array cannot find any occurrence
of the word.
•
- A file provided to an "open" method does not exist.
- A file provided to an "open" method exists, but security prevents the user from using it.
During an attempt to open a network connection to a remote server process, the remote machine
cannot be contacted.
•
- In the middle of a conversation with a remote server process, the network connection stops operating.
12.8. Assertions
An assertion is used to check an invariant, a condition that should always be true. If the assertion is found to
be false then an exception is thrown. If your code assumes that something is true, adding an assertion to test it
gives you a way to catch mistakes before they cause odd effects. For example, in a linked list the last element
in the list usually has a null reference to the next element:
public void append(Object value) {
ListNode node = new ListNode(value);
if (tail != null)
tail.next = node;
tail = node;
assert tail.next == null;
}
When the append method has done its work, the assert double-checks that the last node is properly
formed. If it is not, then an AssertionError is thrown.