3 Types Throwable Exceptions:

Inheritance hierarchy =
	- Throwable (top level)
		- Error (second level - 1)
		- Exception (second level - 2)
			- RuntimeException (third level - 3)

Errors - fatal errors in JVM - no need to program.
Checked Exceptions - subclass Exception - use where client can reasonably recover. Method throws so client must catch and handle. Use if proper API use still may cause an exception and the client can usefully respond to the exception. If both these conditions are not met - use an unchecked exception.
Runtime Exceptions - sublass RuntimeException - indicate programming errors. great majority indicate precondition violations. These should NOT be caught!

NEVER declare "throws Exception" - Totally obscures all checked exception...Argh!

Do NOT ignore exceptions - an empty catch block defeats the purpose of exceptions

Re-use exceptions!
Most common: 
IllegalArgumentException - Parameter value is inappropriate.
IllegalStateException - Object state is inappropriate for method invocation
NullPointerException - Parameter value is null where prohibited
IndexOutOfBoundsException - Index parameter value is out of range
ConcurrentModificationException - Concurrent mod of object has been detected where prohibited
UnsupportedOperationException - Object does not support method (objects that fail to implement one or more ops defined in an interface)

Carry out Exception translation...if necessary chain exceptions...
If low level exception can be worked around then log it and don't translate and
propagate it up.
------------------------------------------------------------------------------------
// Exception chaining JDK 1.4 onwards
MyException(Throwable t)
{
	super(t);
}
------------------------------------------------------------------------------------
//Exception chaining pior to JDK 1.4
private Throwable cause;

MyException(Throwable t)
{
	cause = t;
}

public Throwable getCause()
{
	return cause;
}
------------------------------------------------------------------------------------
Always declare checked exceptions individually and JavaDoc precisely with @throws tag.

Use JavaDoc @throws tag for each unchecked exception method can throw but do not use the throws keyword to include unchecked exceptions in the method declaration
You do not need to declare "throws" for unchecked exceptions but DO document them. They document the preconditions for methods and so are vital for API docs.
Very important to do for interfaces = client contract !

Programmer can easily distinguish between checked & unchecked because method header does not declare throws.

If the same exception type is thrown by many methods then it's OK to document it in the class's doc comment eg. "All methods in this class throw a NullPointerException if a null object reference is passed in any parameter".

To capture the failure, the string representation of an exception should contain the value of all parameters and fields that contributed to the exception.
Note: toString() usually contains class name followed by exception's detail message.
eg. IndexOutOfBounds detail message should contain lower, upper bounds and the failed index value.
It is unimportant to include alot of prose. Uncaught exceptions always give the stack trace
so the code can be looked at. Exceptions are NOT user-level error messages.
To get all the details - build it into the Exception constructor
ie. for IndexOutOfBoundsException:
public IndexOutOfBoundsException(int lowerBound, int upperBound, int index)
{
	super(  "Lower Bound: " +lowerBound +
	      ", Upper Bound: "+upperBound +
	      ", Index: " +index);
}
Accessors methods for these bounds are more important for checked exceptions rather than checked but it is still good practice to have accessors for unchecked exception info.

Make methods failure atomic - a failed method invocation should leave the object in the state that it was in prior to the invocation.

Solutions:
Make object immutable
Check parameter validity first and throw exception before mutating
Write recovery code like DB rollback.
Create a temp copy of object and then replace the original with the copy once operation is complete.

Sometimes failure atomicity cannot be achieved (eg. multiple threads and fails) - if the
object state cannot be guaranteed on exception this should be documented.