再学异常
来源:互联网 发布:淘宝没有人工客服了吗 编辑:程序博客网 时间:2024/06/16 03:35
捕获异常异常处理
1.异常处理有两种基本模式:
- 终止模式:在这种模型中,将假设错误非常关键,以至于程序无法返回到异常发生的地方继续执行,一旦异常被抛出,就表明错误已无法挽回,也不能回来继续执行。(它是Java和c++所支持的模型)
- 恢复模型:异常处理程序的工作是修正错误,然后重新尝试调用出问题的方法,并认为第二次能成功。
创建自定义异常
1.可以用记录日志来关联异常
代码例子:
class LoggingException extends Exception { //创建一个Logger对象 private static Logger logger = Logger.getLogger("LoggingException"); public LoggingException() { //输出字符流 StringWriter trace = new StringWriter(); //将栈跟踪输出到字符流对象 printStackTrace(new PrintWriter(trace)); //使用server日志级别将信息输出到指定对象中 logger.severe(trace.toString()); } } public class LoggingExceptions { public static void main(String[] args) { try { throw new LoggingException(); } catch(LoggingException e) { System.err.println("Caught " + e); } try { throw new LoggingException(); } catch(LoggingException e) { System.err.println("Caught " + e); } } }
运行结果:
二月 26, 2015 9:28:23 下午 beyondboy.LoggingException
严重: beyondboy.LoggingException
at beyondboy.LoggingExceptions.main(LoggingExceptions.java:20)
Caught beyondboy.LoggingException
二月 26, 2015 9:28:25 下午 beyondboy.LoggingException
严重: beyondboy.LoggingException
at beyondboy.LoggingExceptions.main(LoggingExceptions.java:25)
Caught beyondboy.LoggingException
捕获所有异常
1.如果只是把当前异常对象重新抛出,那么printStackTrace()方法显示的将是原来异常抛出点的调用栈信息,而并非重新抛出点的信息,要想更新这个信息,可以调用fillInStackTrace()方法,这将返回一个Throwable对象,它是通过把当前调用栈信息填入原来那个异常对象而建立的(也可以通过使用异常对象的initCause()方法来保留原来的异常信息)。
代码例子:
public class Rethrowing { public static void f() throws Exception { System.out.println("originating the exception in f()"); throw new Exception("thrown from f()"); } public static void g() throws Exception { try { f(); } catch(Exception e) { System.out.println("Inside g(),e.printStackTrace()"); e.printStackTrace(System.out); throw e; } } public static void h() throws Exception { try { f(); } catch(Exception e) { System.out.println("Inside h(),e.printStackTrace()"); e.printStackTrace(System.out); throw (Exception)e.fillInStackTrace(); } } public static void main(String[] args) { try { g(); } catch(Exception e) { System.out.println("main: printStackTrace()"); e.printStackTrace(System.out); } try { h(); } catch(Exception e) { System.out.println("main: printStackTrace()"); e.printStackTrace(System.out); } } }
运行结果:
originating the exception in f()
Inside g(),e.printStackTrace()
java.lang.Exception: thrown from f()
at beyondboy.Rethrowing.f(Rethrowing.java:6)
at beyondboy.Rethrowing.g(Rethrowing.java:10)
at beyondboy.Rethrowing.main(Rethrowing.java:28)
main: printStackTrace()
java.lang.Exception: thrown from f()
at beyondboy.Rethrowing.f(Rethrowing.java:6)
at beyondboy.Rethrowing.g(Rethrowing.java:10)
at beyondboy.Rethrowing.main(Rethrowing.java:28)
originating the exception in f()
Inside h(),e.printStackTrace()
java.lang.Exception: thrown from f()
at beyondboy.Rethrowing.f(Rethrowing.java:6)
at beyondboy.Rethrowing.h(Rethrowing.java:19)
at beyondboy.Rethrowing.main(Rethrowing.java:34)
main: printStackTrace()
java.lang.Exception: thrown from f()
at beyondboy.Rethrowing.h(Rethrowing.java:23)
at beyondboy.Rethrowing.main(Rethrowing.java:34)
2.如果在捕获异常之后抛出另一种异常,有关原来异常发生点的信息会丢失,剩下的是与新的抛出点有关的信息。
class OneException extends Exception { public OneException(String s) { super(s); }}class TwoException extends Exception { public TwoException(String s) { super(s); }}public class RethrowNew { public static void f() throws OneException { System.out.println("originating the exception in f()"); throw new OneException("thrown from f()"); } public static void main(String[] args) { try { try { f(); } catch(OneException e) { System.out.println( "Caught in inner try, e.printStackTrace()"); e.printStackTrace(System.out); throw new TwoException("from inner try"); } } catch(TwoException e) { System.out.println( "Caught in outer try, e.printStackTrace()"); e.printStackTrace(System.out); } }}
运行结果:
originating the exception in f()
Caught in inner try, e.printStackTrace()
beyondboy.OneException: thrown from f()
at beyondboy.RethrowNew.f(RethrowNew.java:14)
at beyondboy.RethrowNew.main(RethrowNew.java:19)
Caught in outer try, e.printStackTrace()
beyondboy.TwoException: from inner try
at beyondboy.RethrowNew.main(RethrowNew.java:24)
使用finally进行清理
1.当Java中的异常不允许我们回到异常抛出的地点时,那么我们可以把try块放在循坏里,就建立了一个”程序继续执行之前必须要达到”的条件。
代码例子:
class ThreeException extends Exception {}public class FinallyWorks { static int count = 0; public static void main(String[] args) { while(true) { try { if(count++ == 0) throw new ThreeException(); System.out.println("No exception"); } catch(ThreeException e) { System.out.println("ThreeException"); } finally { System.out.println("In finally clause"); //跳出while if(count == 2) break; } } }}
运行结果:
ThreeException
In finally clause
No exception
In finally clause
2.如果finally没有正确使用,容易使异常丢失。
代码例子:
class VeryImportantException extends Exception { public String toString() { return "A very important exception!"; } } class HoHumException extends Exception { public String toString() { return "A trivial exception"; } } public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(); } void dispose() throws HoHumException { throw new HoHumException(); } public static void main(String[] args) { try { LostMessage lm = new LostMessage(); try { lm.f(); } finally { lm.dispose(); } } catch(Exception e) { System.out.println(e); } } }
运行结果:
A trivial exception
异常的限制
1.当覆盖方法的时候,只能抛出在基类方法的异常说明列出的那些异常,派生类构造器的异常说明必须包含基类构造器的异常说明,而不能捕获基类构造器抛出的异常,当派生类覆盖有抛出异常的基类方法时,可以不带有异常说明,但当覆盖没有抛出异常的基类方法时,不可以带有异常说明。
代码例子:
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 rainHard() throws RainedOut;}public class StormyInning extends Inning implements Storm { //可以增加抛出新的异常,但必需包含基类的构造器的异常 public StormyInning() throws RainedOut, BaseballException {} public StormyInning(String s) throws Foul, BaseballException {} //基类的这个方法没有声明抛出异常,所以会编译错误//! void walk() throws PopFoul {} //不能改变其基类定义抛出的异常说明//! public void event() throws RainedOut {} // 这个可以抛出任何异常 public void rainHard() throws RainedOut {} //不能抛出任何异常 public void event() {} //重写可以抛出基类抛出其异常的子类 public void atBat() throws PopFoul {} public static void main(String[] args) { try { StormyInning si = new StormyInning(); si.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"); } try { // 向上转型 Inning i = new StormyInning(); i.atBat(); //必须根据来基类的方法抛出的异常类型来捕捉 } catch(Strike e) { System.out.println("Strike"); } catch(Foul e) { System.out.println("Foul"); } catch(RainedOut e) { System.out.println("Rained out"); } catch(BaseballException e) { System.out.println("Generic baseball exception"); } }}
构造器
1.在关闭物理资源中,由于finally会每次都执行清理代码,如果构造器在其执行过程中半途而废,也许该对象的某些部分还没有被成功创建,而这些部分在finally子句中却要被清理,这样就会产生矛盾,如果构造器有抛出异常,应该在创建需要清理的对象之后,立即进入一个try-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 CleanupIdiom { public static void main(String[] args) { // 第一种创建一个构造器没有异常对象的清理情况 NeedsCleanup nc1 = new NeedsCleanup(); try { } finally { nc1.dispose(); } // 第二种创建多个构造器没有异常对象的清理情况 NeedsCleanup nc2 = new NeedsCleanup(); NeedsCleanup nc3 = new NeedsCleanup(); try { // ... } finally { nc3.dispose(); nc2.dispose(); } //第三种创建多个构造器可能会抛出异常对象的清理情况 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); } } }
运行结果:
NeedsCleanup 1 disposed
NeedsCleanup 3 disposed
NeedsCleanup 2 disposed
NeedsCleanup 5 disposed
NeedsCleanup 4 disposed
异常匹配
1.当处理被检查异常时,编译器可能会强制你在可能还没准备好处理错误的时候被迫加上catch句子,也许就导致了“吞食则有害”的问题,这里可以通过异常链的方法将检查异常转换成不检查的异常。
代码例子:
块处理这不检查的异常 wce.throwRuntimeException(3); //测试各种异常类型 for(int i = 0; i < 4; i++) try { if(i < 3) wce.throwRuntimeException(i); else throw new SomeOtherException(); } catch(SomeOtherException e) { System.out.println("SomeOtherException: " + e); } catch(RuntimeException re) { try { //获取最原始的异常信息 throw re.getCause(); } catch(FileNotFoundException e) { System.out.println("FileNotFoundException: " + e); } catch(IOException e) { System.out.println("IOException: " + e); } catch(Throwable e) { System.out.println("Throwable: " + e); } } } }
运行结果:
FileNotFoundException: java.io.FileNotFoundException
IOException: java.io.IOException
Throwable: java.lang.RuntimeException: Where am I?
SomeOtherException: beyondboy.SomeOtherException
- 再学异常
- 再学java基础(8)【 异常 】 (借鉴)
- 再学java基础(8)【 异常 】 (借鉴)
- groovy 速学 - 07 - 异常
- 新手学Python 第十篇 异常
- 从头开始学java--异常处理
- 菜鸟学java:NullPointerException异常的解决。
- 零基础学python-2.18 异常
- 从零开始学C++之异常(三):异常与继承、异常与指针、异常规格说明
- 从零开始学C++之异常(三):异常与继承、异常与指针、异常规格说明
- 从零开始学C++之异常(三):异常与继承、异常与指针、异常规格说明
- 二十一天学通C++之异常概述
- 二十一天学通C++之异常处理机制
- 二十一天学通C++之异常处理机制
- 菜鸟学Java(十八)——异常
- go 速学 - 10 - defer 与异常处理
- 《笨方法学python-5》之异常处理
- 一步步学spark之一scala的异常处理1.7
- Android AlertDialog对话框自定义风格的另类实现
- cocoapods导致的符号重复问题分析和解决
- CODEVS-3303-翻转区间
- Linux 命令16-which命令
- 互联网模式的企业如何运维IT系统(二)
- 再学异常
- Django使用redis做cache
- c_指针_一维数组名作为函数参数
- AJAX调试技术 IE篇
- UVA12108 Extraordinarily Tired Students(超级大模拟)
- 使用事件总线框架EventBus和Otto
- Linux 命令17-whereis命令
- [CXF REST标准实战系列] 二、Spring4.0 整合 CXF3.0,实现测试接口
- Linux 命令18-locate命令