Exceptions in Java can disrupt normal program flow and are divided into checked exceptions which can be recovered from, errors which cannot be recovered from, and unchecked exceptions which usually indicate bugs. There are best practices for exceptions such as never swallowing them, throwing specific exceptions, catching specific subclasses, logging or rethrowing exceptions, and avoiding returns or throws in finally blocks.