My rule of thumb:
Exceptions are used for run-time error conditions (IO errors, out of memory, can't get a database connection, etc.).
Assertions are used for coding errors (this method doesn't accept nulls, and the developer passed one anyway).
For libraries with public classes, throw exceptions on the public methods (because it makes sense to do so). Assertions are used to catch YOUR mistakes, not theirs.
EDIT: This may not be entirely clear, due to the null value example. My point is that you use assertions (as others have pointed out) for conditions that should NEVER happen, for conditions that should NEVER make it into production code. These conditions absolutely must fail during unit testing or QA testing.