构造器异常

有时我们会想:“如果异常发生了,所有的东西都能被正确清理吗?”

当涉及到构造器时,又会怎样呢?

总结来说:在构造器内,如果抛出了异常,那么此时这些清理行为也许不能正常工作。

我们还需要考虑的是:如果构造器在其执行过程中半途而废了,也许该对象的某些部分还没有被成功创建,而这些部分在finally子句中确是要被清理的。在这,我们还能用finally来解决这个问题吗?

答案是不能的,我们对于那些在构造阶段可能会抛出异常,并且要求清理的类,最安全的方式就是使用嵌套的try子句。

这种通用的清理法既使在构造器不抛出异常时,我们也应该应用,规则:在创建需要清理的对象之后,立即进入一个try-finally语句块:

class NeedsCleanup{
	//construction can't fail
	private static long counter = 1;
	private final long id = counter ++;
	public void dispose() {
		System.out.println("NeedCleanup" + id + "disposed");
	}
}
class ConstructionException extends Exception{}

class NeedsCleanup2 extends NeedsCleanup{
	//Construction can fail
	public NeedsCleanup2() throws ConstructionException{	
	}
}
public class CleanupIdiom {
	public static void main(String[] args) {
		//Section 1:
		NeedsCleanup nc1 = new NeedsCleanup();
		try {
			//...
		}finally {
			nc1.dispose();
		}
		
		//Section 2:
		//If construction cannot fail you can group objects
		NeedsCleanup nc2 = new NeedsCleanup();
		NeedsCleanup nc3 = new NeedsCleanup();
		try {
			//...
		}finally {
			nc3.dispose(); //Reverse order of construction
			nc2.dispose();
		}
		
		//Section 3:
		//If construction can fail you must guard each one
		try {
			NeedsCleanup2 nc4 = new NeedsCleanup2();
			try {
				NeedsCleanup2 nc5 = new NeedsCleanup2();
				try {
					//...
				}finally {
					nc5.dispose();
				}
				
			}catch(ConstructionException e) {
				System.out.println(e);
			}finally {
				nc4.dispose();
			}
			
		}catch(ConstructionException e) {
			System.out.println(e);
		}	
	}
}class NeedsCleanup{
	//construction can't fail
	private static long counter = 1;
	private final long id = counter ++;
	public void dispose() {
		System.out.println("NeedCleanup" + id + "disposed");
	}
}
class ConstructionException extends Exception{}

class NeedsCleanup2 extends NeedsCleanup{
	//Construction can fail
	public NeedsCleanup2() throws ConstructionException{	
	}
}
public class CleanupIdiom {
	public static void main(String[] args) {
		//Section 1:
		NeedsCleanup nc1 = new NeedsCleanup();
		try {
			//...
		}finally {
			nc1.dispose();
		}
		
		//Section 2:
		//If construction cannot fail you can group objects
		NeedsCleanup nc2 = new NeedsCleanup();
		NeedsCleanup nc3 = new NeedsCleanup();
		try {
			//...
		}finally {
			nc3.dispose(); //Reverse order of construction
			nc2.dispose();
		}
		
		//Section 3:
		//If construction can fail you must guard each one
		try {
			NeedsCleanup2 nc4 = new NeedsCleanup2();
			try {
				NeedsCleanup2 nc5 = new NeedsCleanup2();
				try {
					//...
				}finally {
					nc5.dispose();
				}
				
			}catch(ConstructionException e) {
				System.out.println(e);
			}finally {
				nc4.dispose();
			}
			
		}catch(ConstructionException e) {
			System.out.println(e);
		}	
	}
}

代码分析:

在main()中,Section 1是比较简单的,遵循了在可去除对象之后紧跟try-finally的原则。构造失败,我们不需要使用catch。

                     Section 2是为了构造和清理,可以看到具有不能失败的构造器对象可以群组在一起。

                     Section 3:是显示了如何处理那些具有可以失败的构造器,且需要清理的对象。这对于每一个构造器来说,都必须包含在其自己的try-finally语句块中,并且每一个对象构造器都必须跟随一个try-finally语句块以保证正确清理。

运行结果:


 

猜你喜欢

转载自blog.csdn.net/qq_41026809/article/details/92798491
今日推荐