(1)异常的限制
当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这个限制很有用,因为这意味着,当基类使用的代码应用到期派生类对象的时候,一样能够工作。
public class ExceptionRestrictionTest extends Inning implements Storm
{
//必须处理基类构造函数所抛出的异常,同时,可以加入新的异常
//方法中声明抛出异常,方法体中也可以不抛出异常
public ExceptionRestrictionTest() throws BaseballException,RainedOut
{
throw new BaseballException();
}
//普通方法必须与基类保持一致,基类没有抛出异常,则覆盖的方法也不能抛出异常
//public void walk() throws PopFoul{}
//接口不能添加新的exception到基类中已经存在的方法
//public void event()throws BaseballException,RainedOut{}
//如果接口中的方法在基类中不存在,那么接口可以添加exception
public void rainHard() throws RainedOut{}
//可以选择不抛出基类方法抛出的异常
public void event(){}
//覆盖的方法可以抛出基类方法抛出的异常的子类
public void atBat() throws PopFoul{}
public static void main(String[] args)
{
try
{
ExceptionRestrictionTest ert=new ExceptionRestrictionTest();
ert.atBat();
}
catch(PopFoul e)
{
System.out.println("Pop foul");
}
catch(RainedOut e)
{
System.out.println("Rained out");
}
catch(BaseballException e)
{
System.out.println("Generic baseball exception");
}
//不用捕获基类atBat()方法抛出的异常
try
{
Inning i=new ExceptionRestrictionTest();
//向上转型时捕获基类的异常
i.atBat();
}
catch(Strike e)
{
System.out.println("Strike");
}
catch(Foul e)
{
System.out.println("Generic baseball exception");
}
catch(RainedOut e)
{
System.out.println("Rained out");
}
catch(BaseballException e)
{
System.out.println("Generic baseball exception");
}
}
}
class BaseballException extends Exception{}
class Foul extends BaseballException{}
class Strike extends BaseballException{}
abstract class Inning
{
public Inning() throws BaseballException{}
public void event() throws BaseballException{}
public abstract void atBat() throws Strike,Foul;
public void walk(){}
}
class StormException extends Exception{}
class RainedOut extends StormException{}
class PopFoul extends Foul{}
interface Storm
{
public void event() throws RainedOut;
//public void event()throws BaseballException;
public void rainHard() throws RainedOut;
}
(2)构造器与异常
对于在构造阶段会抛出的异常,并且要求清理的类,最安全的使用方式是使用嵌套的try字句。
这种通用的清理惯用法在构造器不抛出任何异常时也应该运用,其基本规则是:在创建了需要清理的对象之后,立即进入try-finally语句块,并在finally字句下进行清理工作。
class NeedsCleanup
{
private static long counter=1;
private final long id=counter++;
public void dispose()
{
System.out.println("NeedsCleanup"+id+"disposed");
}
}
class ConstructionException extends Exception{}
class NeedsCleanup2 extends NeedsCleanup
{
public NeedsCleanup2() throws ConstructionException{};
}
public class Cleanup
{
public static void main(String[] args)
{
//section 1:
//如果构造器不会抛出异常,可以在一个层次上新建两个实例
NeedsCleanup nc1=new NeedsCleanup();
NeedsCleanup nc2=new NeedsCleanup();
try
{
}
finally
{
//dispose的调用顺序与构造顺序相反
nc2.dispose();
nc1.dispose();
}
//section 2:
//如果构造器会抛出异常,则必须使用嵌套层次捕获构造的异常
try
{
NeedsCleanup2 nc3=new NeedsCleanup2();
try
{
try
{
NeedsCleanup2 nc4=new NeedsCleanup2();
try
{
}
finally
{
nc4.dispose();
}
}
catch (ConstructionException e)
{
System.out.println(e);
}
}
finally
{
nc3.dispose();
}
}
catch(ConstructionException e)
{
System.out.println(e);
}
}
}