{Effective Java} Chap 9 Exceptions

使用异常提升程序的可读性、可靠性和维护性
本文详细阐述了如何正确使用异常处理来改进程序的可读性、可靠性和维护性,包括如何仅在异常情况下使用异常,如何选择在状态测试方法还是使用返回值,以及如何避免不必要的检查异常的使用。同时,文章还提供了关于如何使用标准异常、抛出适当异常、文档异常、失败捕获信息和失败原子性的指导。



When used properly, exceptions can improve a program's readability, reliability and maintainability.

Item 57: Use exceptions only for exceptional conditions

Exceptions are to be used only for exceptional conditions, they should never be used for orinary control flow.

A well-designed API must not force its clients to use exceptions for ordinary control flow. 

Guidelines that help choose between a state-testing method and a distinguished return value:

If an object is to be accessed concurrently without external synchronization or is subject to externally induced state transitions, you must use return value. Because the object's state could change in the interval between the invocation of a state-testing method and its state-dependent method.

If a state-testing method duplicate the work, we should use return value.

In other conditions, use state-testing methods.


In summary, exceptions are designed for use in exceptional conditions. Don't use them for ordinary control flow and dont write APIs that force others to do so.



Item 58: Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

Checked Exception, Runtime exceptions and error (both are throwables and shouldn't be caught).

Most runtime exceptions indicate precondition violations. 

JVM throws errors such as resource deficiencies, invariant failures and other conditions that make it impossible to continue execution.

All of the unchecked throwables you implement should subclass RuntimeException.


To summarize, because checked exceptions generally indicate recoverable conditions, it's especially important for such exceptions to provide methods that furnish information that could help the caller to recover. 



Item 59: Avoid unnecessary use of checked exceptions

If the programmer using the API can do no better, an unchecked exception would be more appropriate. 

If it is the sole checked exception thrown by a method, the burden is higher.


Item 60: Favor the use of standard exceptions

Experts strive for a high degree of code reuse.

Reusing preexisting exceptions has several benefits. 

makes your API easier to learn and use, read. Fewer exception classes mean a smaller memory footprint and less time spent loading classes.


IllegalArgumentException --- checks whether arguments values are valid. Non-null parameter value is inappropriate.

IllegalStateException --- thrown if the invocation is illegal because of the state of the receiving object. 

ConcurrentModificationException --- used by a single thread or with external synchronization detects that it is being concurrently modified. 

UnsupportedOperationException --- checks the attempted operation.

NullPointerException --- Parameter value is null where prohibited.

IndexOutOfBoundsException --- index parameter value is out of range.



Item 61: Throw exceptions appropriate to the abstraction

Higher layers should catch lower-level exceptions and in their place, throw exceptions that can be explained in terms of the higher-level abstraction.

Exception translation / chaining

	/**
	 * Returns the element at the specified position in this list.
	 * 
	 * @thows IndexOutOfBoundsException if the index is out of range.
	 *        {@code index < 0 || index >= size()}
	 */
	public E get(int index){
		ListIterator<E> i = listIterator<index>;
		try {
			return i.next;
		} catch (NoSuchElementException e) {
			throw new IndexOutOfBoundsException("Index: " + index);
		}
	}


While exception translation is superior to mindless propagation of exceptions from lower layers, it should not be overused.

	//Exception Chaining
	try{
		... // Use lower-level abstraction to do our bidding
	}catch(LowerLevelException cause){
		throw new HigherLevelException(cause);
	}
	
	
	//Exception with chaining-aware constructor
	class HigherLevelException extends Exception{
		HigherLevelException(Throwable cause) {
			super(cause);
		}
	}



In summary, if it isn't feasible to prevent or to handle exceptions from lower layers, use exception translation, unless the lower-level method happens to guarantee that all of its exceptions are appropriate to the higher level. Chaining provides the best of both worlds: it allows you to throw an appropriate higher-level exception, while capturing the underlying cause for failure analysis.


Item 62: Document all exceptions thrown by each method 

Always declare checked exceptions individually, and document precisely the conditions under which each one is thrown using the Javadoc @throws tag.

Never declare a method that throws Exception, which obscures other exceptions that may be thrown.

Documenting its unchecked exceptions is the best way to describe preconditions.

Use Javadoc @thorws tag to document each unchecked exception that a method can throw, but do not use the throws keyword to include unchecked exceptions in the method declaration.

If an exception is thrown by many methods in a class for the same reason, it is acceptable to document the exception in the class's documentation comment. E.g NullPointerException


In summary, document every exception that can be thrown by each method. 



Item 63: Include failure-capture information in detail messages

To capture the failure, the detail message of an exception should contain the values of all parameters and fields that contributed to the exception.

The detail message of an exception should not be confused with a user-level error message, which must be intelligible to end users.

Require failure information in their constructors instead of a string detail message.

E.g

/**
	 * Construct an IndexOutOfBoundsException.
	 * 
	 * @param lowerBound the lowest legal index value.
	 * @param upperBound the highest legal index value plus one.
	 * @param index the actual index value.
	 */
	public IndexOutOfBoundsException(int lowerBound, int upperBound, int index){
		//Generate a detail message that captures the failure
		super("Lower bound: " + lowerBound + ", Upper bound: " + upperBound + ", Index: " + index);
		
		//Save failure information for programmatic access
		this.lowerBound = lowerBound;
		this.upperBound = upperBound;
		this.index = index;
	}



It is important to provide accessor methods on checked exceptions than on unchecked exception.



Item 64: Strive for failure atomicity

Generally speaking, a failed method invocation should leave the object in the state that it was prior to the invocation.

1. design immutable objects, whose state is consistent when it is created and can't be modified thereafter.

Check parameters for validity before performing the operation.

2. order the computation so that any part that may fail takes place before any part that modifies the object. 

3. write recovery code that intercepts a failure, most used for durable (disk-based) data structures.

4. perform the operation on a temporary copy and substitude original one once the operation is complete.


public Object pop(){
		if(size == 0)
			throw new EmptyStackException();
		Object result = elements[-- size];
		elements[size] == null;  //Eliminate obsolete reference
		return result;
	}



As a rule, errors are unrecoverable, and methods need not even attempt to preserve failure atomicity when throwing errors.

As a rule, any generated exception that is part of a method's specification should leave the object in the same state it was in prior to the method invocation. If violated, need API documentation the state.



Item 65: Don't ignore exceptions

An empty catch block defeats the purpose of exceptions.

At the every least, the catch block should contain a comment explaining why it is appropriate to ignore the exception.

Properly handling an exception can avert failure entirely.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Anyanyamy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值