Checked exceptions generally corresond to problems that are
not programmer errors.
A typical example is a program that prompts a user for an input
file name. The programmer cannot prevent the user from typing an
incorrect file name. FileNotFoundException, a checked
exception, then results when an attempting to open the file.
A program should be prepared to catch a checked exception and
possibly attempt some recovery or at the least to exit gracefully.
In the example, the program could report the invalid file name and
prompt the user to try again.
Java language requires that a method that makes calls that can
throw a checked exception must catch the exception or else declare
that it will (indirectly) cause the checked exceptionto be thrown.
However, this deferral of catching exceptions should not
include the main method of a finished application.
Unchecked exceptions on the other hand should not occur if the
program has been written carefully. Examples include passing
inappropriate values to methods, calling methods when the state of
the instance forbids it, and accessing arrays with a subscript out of
bounds.
Generally a class will provide ways of checking any
preconditions for calling its methods and so a program can be written
to ensure that unchecked exceptions will not occur.
Error classes can also be thrown, but are not derived
from Exception.
Error types are also unchecked (but they are unchecked Errors, not
unchecked Exceptions).
Errors and unchecked exceptions are both unchecked
throwables.
The convention is that errors should only be thrown by the java
virtual machine to indicate conditions that make it impossible
to continue (e.g. disk failure, stack overflow, etc.)
User class methods should not throw Error or any of its derived
class types.
Throwable
|
+-------+------------------+
| |
Exception Error
| |
+------------------+ unchecked classes...
| |
RunTimeException checked classes ...
|
unchecked classes
- Identify preconditions for the methods in classes you
write.
- In each method check if its preconditions are met. If not,
throw an appropriate exception.
- Include methods in your class that lets the user of the
class test whether preconditions regarding the state of a class
instance are met.
- Stick to the standard Java exception classes if
possible. Usually you can find one that is appropriate for your
purposes without having to create new Exception classes.
A short list of commonly used java unchecked exceptions:
- IndexOutOfBoundsException (unchecked)
- IllegalArgumentException (unchecked)
- IllegalStateException (unchecked)
- NoSuchElementException (unchecked)
- UnsupportedOperationException (unchecked)
The Scanner next() method reads the next
word.
But the default meaning of word is whitespace delimited
sequence of input characters.
The delimiter pattern can be changed using Scanner's
useDelimiter method.
The argument to useDelimiter should be string
representing a pattern. Then any sequences of characters that
match the pattern will be treated as the delimiter to use in
determining the words by the Scanner.
Patterns are spcified by regular expressions
Characters
\t The tab character
\n The newline (line feed) character
\r The carriage-return character
\f The form-feed character
\a The alert (bell) character
\e The escape character
Character Classes
[abc] a, b, or c (simple class)
[^abc] Any character except a, b, or c (negation)
[a-zA-Z] a through z or A through Z, inclusive (range)
Predefined Character Classes
. Any character (may or may not match line terminators)
\d A digit: [0-9]
\D A non-digit: [^0-9]
\s A whitespace character: [ \t\n\x0B\f\r]
\S A non-whitespace character: [^\s]
\w A word character: [a-zA-Z_0-9]
\W A non-word character: [^\w]
Warning: \ is used as an escape for
characters; that is, '\n' or "\n" doesn't mean the
character n. The usual meaning of character n is
"escaped" and '\n' has the special meaning: the newline character.
The predefined character classes are not single characters, so
this interfers with the use of \ as a escape character. That is,
\s has no special meaning as a single character. The way
Java deals with this is to escape the \ inside a string:
"n" string with 1 n
"\n" string with 1 newline
"s" string with 1 s
"\s" Error \s is an illegal escaped character
"\\s" String indicating the character class of any whitespace character
How do you write a pattern that matches 1, 2, 3, or more
whitespace characters?
Answer: Use a multiplier:
A * following a regular expression means 0 or more
occurrences.
A + following a regular expression means 1 or more
occurrences.
So,
"\\s*,\\s*" matches 0 or more whitespace characters followed by
a comma, followed by 0 or more whitespace
characters.
"[ \r\t\n]+" (What does this match?)
"[\\s,.!?]+" (What does this match?)
import java.util.Scanner;
public class ReadCSV
{
public static void main(String[] args)
{
Scanner in = null;
try {
in = new Scanner(new File(args[0]));
} catch(FileNotFoundException e) {
System.out.printf("Unable to open input file %s\n", args[0]);
System.exit(0);
}
String[] fields;
String line;
while( in.hasNextLine() ) {
line = in.nextLine();
fields = line.split("\\s*,\\s*");
for(int i = 0; i < fields.length; i++) {
System.out.printf("field %d: %s\n", i, fields[i]);
}
}
}
}
Input items should be compared to a allowed
items. Display the input items not in the allowed list.
For each input item a search is required to see if it is
in the allowed list.
How are the allowed items to be stored?
How will the allowed items be searched for each input item?
Allowed items could be stored in an ordinary array. How big
should the array be?
Alternatively items could be stored in an ArrayList.
In this example, assume for the moment that the allowed list is
stored in an array and will not be modified.
Linear search of an array of keys for an item examines
each array element until the item is found or until all array
elements have been compared with no match.
For examle, assuming the keys are of type int, this
rank function returns the array index where item
is found or -1 if not found.
public int rank(int[] keys, int item)
{
for(int i = 0; i < keys.length; i++) {
if ( item == keys[i] ) {
return i;
}
}
return -1;
}
Instead of examining every array element (e.g., when item is not
found), binary search will examine many fewer items.
For example, if there are 1024 keys, linear search for an item
not in the array will examine all 1024 keys.
Binary search, will examine only about 10 keys.
However, for the array must be sorted!
public int rank(int[] keys, int item)
{
int lo = 0;
int hi = keys.length - 1;
while(lo <= hi) {
int mid = (lo + hi) / 2;
if ( keys[mid] == item ) {
return mid;
} else if ( item < keys[mid] ) {
hi = mid - 1;
} else {
lo = mid + 1;
}
}
return -1;
}
This version
- reads the keys into an array
- reads items from standard input
- for each item, print if not found in the array
public class LinearSearch
{
private static int rank(int[] keys, int item)
{
// linear search implementation above
...
}
public static void main(String[] args)
{
int[] keys = StdIn.readInts(args[0]);
while(!StdIn.isEmpty()) {
int item = StdIn.readInt();
if ( rank(keys, item) == - 1 ) {
System.out.println(item);
}
}
}
}
This version is similar, but uses binary search.
import java.util.Arrays;
public class BinarySearch
{
private static int rank(int[] keys, int item)
{
// binary search implementation above
...
}
public static void main(String[] args)
{
int[] keys = StdIn.readInts(args[0]);
Arrays.sort(keys);
while(!StdIn.isEmpty()) {
int item = StdIn.readInt();
if ( rank(keys, item) == - 1 ) {
System.out.println(item);
}
}
}
}
The client code above is not too complicated, but even in this
case, can be made clearer and less dependent on the
implementation (i.e., the data representation and/or the search implementation).
USe a SetOfInts class that stores the data from an array of
keys and provides a public contains method.
public class SetOfInts
{
private int[] keys;
public SetOfInts(int[] a)
{
keys = a;
Arrays.sort(keys);
}
private int rank(int item)
{
// binary search version of rank
...
}
public boolean contains(item)
{
return rank(item) != -1;
}
}
This version uses the SetOfInts ADT.
public class Filter
{
public static void main(String[] args)
{
int[] keys = StdIn.readInts(args[0]);
SetOfInts s = new SetOfInts(keys);
while(!StdIn.isEmpty()) {
int item = Stdin.readInt();
if (!s.contains(item) ) {
System.out.println(item);
}
}
}
}
A stack type should allow insertions and deletions such that the
item deleted is the last one inserted - last in, first out.
We might also want to know if the stack is empty and if not, to
be able to examine the last item inserted.
The data type should be stored in the stack will not affect the
stack operations.
So use a generic type variable, say E, for this data.
The UML diagram below gives the syntactic specification
of the Stack class, but nothing about the actual meaning; i.e.,
the last-in, first-out property.
What is needed is additional documentation of the method properties.
Stack<E> |
.. private data .. |
+Stack()
+void push(E x)
+E pop()
+E peek()
+boolean isEmpty()
+int size()
|
/**
* The Stack class represents a last-in, first-out data type.
*
* @author glancast
*/
public class Stack<E>
{
/**
* Creates an empty Stack
*
*/
public Stack()
{}
/**
* Inserts an item on the top of this Stack.
*
* @param x the item to be inserted
*/
public void push(E x)
{}
/**
* Removes the last inserted item on the stack
* and returns that object as the return value of
* this method.
*
* @return The item removed from the top of the stack.
* @throws NoSuchElementException if the stack is empty.
*/
public E pop()
{}
/**
* Returns the last inserted item on the the stack without
* removing it.
*
* @return The item at the top of the stack.
* @throws NoSuchElementException if the stack is empty.
*/
public E peek()
{}
/**
* Test if this stack is empty.
* @return true if the stack is empty; false, otherwise.
*/
public boolean isEmpty()
{}
/**
* Get the number of elements in this stack.
*
* @return the number of elements
*/
public int size()
{}
}
We could use an array (with elements of the generic element
type E) to store the elements of the stack.
But an array is fixed size, so it doesn't actually grow or shrink as
items are inserted or deleted.
We could keep track of two things:
- Actual size of the array - capacity.
- The number of items logically inserted in the array - sz.
Then,
The last item will be at index sz - 1
-
The stack is empty if sz == 0
-
Insertion (push) just stores the item at position
sz and then increments sz.
-
Deletion (pop) can copy the value at position sz -
1 to be returned. Then it can set this value to null,
decrement sz and returns the copied value.
This can work, but the major problem is the size of the
array. The push method cannot do its job if the array is full!
This can be overcome by using an ArrayList instead of
an ordinary array since an ArrayList grows as needed when elements
are added.