异常与错误

程序的错误可以抽象分为三类:语法错误、运行错误和逻辑错误
语法错误

是指由于编程中输入不符合语法规则而产生的。程序编译就通不过,程序不能运行起来。此类错误最简单,调试起来比较容易。例如:表达式不完整、缺少必要的标点符号、关键字输入错误、数据类型不匹配、循环语句或选择语句的关键字不匹配等。通常,编译器对程序进行编译的过程中,会把检测到的语法错误以提示的方式列举出来,又称为编译错误。语法错误的调试,则可以由集成开发环境提供的调试功能来实现,在程序进行编译时,编译器会对程序中的语法错误进行诊断。

编译诊断的语法错误分为3种:

    (1)致命错误:这个错误大多是编译程序内部发生的错误,发生这类错误时,编译被迫中止,只能重新启动编译程序,但是这类错误很少发生,为了安全,编译前最好还是先保存程序。
    (2)错误:这个错误通常是在编译时,语法不当所引起的。例如:括号不匹配,变量未声明等。产生这类错误时,编译程序会出现报错提示,我们根据提示对源程序进行修改即可。这类错误是出现最多的。
    (3)警告:是指被编译程序怀疑有错,但是不确定,有时可强行通过。例如:没有加void声明的主函数没有返回值,double数据被转换为float类型等。这些警告中有些会导致错误,有些可以通过。

常规解决方法:此类错误一般程序编译系统会自动提示相应的错误地点和错误原因,比如哪一行代码少了个括号等诸如此类的提示,常见的错误,看懂直接改正即可,如果是看不懂原因,可以将错误提示信息输入搜索引擎查找一下,一般都能找到具体的解决办法。或者有些编程平台会本身提供一个本地或者在线的信息库,提供详细的错误原因和解决办法,比如微软的.NET开发平台。 

运行错误

指程序在运行过程中出现的错误。程序通过语法错误检测,但是运行的时候出现错误,导致程序被迫终止,此类错误有特定的发生条件,因此能够准确的定位错误代码段,因而调试也比较方便。

例如:除法运算时除数为0 、数组下标越界、文件打不开、磁盘空间不够、数据库连接错误等。

此类错误发生时,编译平台一般也会提示相应的信息,对于常规的错误会有比较精确地提示,但有时提示的错误原因会比较模糊,但因为此类错误一般在程序运行时,只在特定的条件下才会发生,所以根据错误发生的条件,能够大致判断程序出错的代码段,结合错误的原因,也能比较方便的调试出错误。

逻辑错误

程序运行后,没有得到设计者预期的结果,这就说明程序存在逻辑错误。这种错误在语法上是有效的,但是在逻辑上是错误的。

程序运行了,也没有出错,但是执行出来的结果不是用户想要的,分为两种情况:

A、 能够看出错误:比如查询工资大于5000的人员名单,却出现了3000的;

B、 看不出错误,直到因缘际会发现程序肯定出错了,后果很严重:比如进行一个符合大型运算,把某个常数输入错了,最后的结果人工无法判断对错,又以该结果进行其它的运算等等,最后发现错了误差过大,就得从头排查错误。

例如:使用了不正确的变量,指令的次序错误,循环的条件不正确,程序设计的算法考虑不周全等。通常,逻辑错误也会附带产生运行错误。在一般情况下,编译器在编译程序时,不能检测到程序中的逻辑错误,也不会产生逻辑错误的提示,因此逻辑错误比较难排除,需要程序员仔细的分析程序,并借助集成开发环境提供的调试工具,才能找到出错的原因,并排除错误。


java的异常处理(错误处理)

程序的错误就是通常的异常,也叫Exception。

对于语法错误,java编译系统在编译就能发现检查出错误。

对于逻辑错误,编译系统是无法发现错误的,错误需要人为去发现排除错误。

对于运行错误,Java语言中代表异常时,使用一个专门的类来代表一种特定的异常情况,在系统中传递的异常情况就是该类的对象,所有代表异常的类组成的体系就是Java语言中的异常类体系。 

java异常类

Java的异常是一个对象,所有的异常都直接或间接地继承Throwable类。Throwable类的继承层次结构如下:

 

为了方便对于这些可传递对象的管理,Java API中专门设计了java.lang.Throwable类,只有该类子类的对象才可以在系统的异常传递体系中进行。该类的两个子类分别是:

1)Error类 

该类代表错误,指程序无法恢复的异常情况。对于所有错误类型以及其子类,都不要求程序进行处理。常见的Error类例如内存溢出StackOverflowError等。 

2)Exception类 

该类代表异常,指程序有可能恢复的异常情况。该类就是整个Java语言异常类体系中的父类。使用该类,可以代表所有异常的情况。 

在Java API中,声明了几百个Exception的子类分别来代表各种各样的常见异常情况,这些类根据需要代表的情况位于不同的包中,这些类的类名均以 Exception作为类名的后缀。如果遇到的异常情况,Java API中没有对应的异常类进行代表,也可以声明新的异常类来代表特定的情况。

在这些异常类中,根据是否是程序自身导致的异常,将所有的异常类分为两种: 

a)RuntimeException及其所有子类 

该类异常属于程序运行时异常,也就是由于程序自身的问题导致产生的异常,例如数组下标越界异常ArrayIndexOutOfBoundsException等。 

该类异常在语法上不强制程序员必须处理,即使不处理这样的异常也不会出现语法错误。 

b)其它Exception子类 

该类异常属于程序外部的问题引起的异常,也就是由于程序运行时某些外部问题导致产生的异常,例如文件不存在异常FileNotFoundException等。 

该类异常在语法上强制程序员必须进行处理,如果不进行处理则会出现语法错误。 

熟悉异常类的分类,将有助于后续语法中的处理,也使得在使用异常类时可以选择恰当的异常类类型。

常见运行时异常类

异常类名

用途

ArithmeticException

数学运算异常,比如除数为零的异常

IndexOutOfBoundsException

下标越界异常,比如集合、数组等

ArrayIndexOutOfBoundsException

访问数组元素的下标越界异常

StringIndexOutOfBoundsException

字符串下标越界异常

ClassCaseException

类强制转换异常

NullpointerException

当程序试图访问一个空数组中的元素,或访问一个空对象中的方法或变量时产生的异常。

常用的非运行时异常

异常类名

用途

ClassNotFoundException

指定类或接口不存在的异常

IllegalAccessException

非法访问异常

Ioexception

输入输出异常

FileNotFoundException

找不到指定文件的异常

ProtocolException

网络协议异常

SocketException

Socket操作异常

MalformedURLException

统一资源定位符(URL)的格式不正确的异常


异常的抛出

异常的抛出可以分为两大类:

1、系统自动抛出异常

2、通过关键字throw将异常对象显性地抛出。

即在程序中生成自己的异常对象,即异常可以不是出错产生,而是人为编写代码主动抛出。显性抛出异常从某种程度上实现了将处理异常的代码从正常流程代码中分离开了,使得程序的主线保证相对完整,同时增加了程序的可读性和可维护性。异常沿着调用层次向上抛出,交由调用它的方法来处理。

为什么要在方法中抛出异常?

系统自动抛出异常一般就能解决大部分问题,但有时候,程序会产生特定的要求,需要由用户自己定义异常信息,又或者联合开发程序模块时,不同程序员需要将各自负责代码部分尽量避免因程序出错影响其他人的编码,都需要显式抛出异常,以便程序进行处理。这时候就需要在方法中抛出异常。


推荐catch块使用return,因为如果出现异常,后续的操作一般会受到影响,大多数情况不应该再执行,这时应该处理完异常就结束;当然也可以解决异常,然后让后续的代码继续执行

如果对异常不作捕获处理,则在发生异常的时候,函数便终止,发生异常的地方后面的代码当然也不会执行,如:

   publicvoid testTry() throws Exception{

      Integer.parseInt("d");

      System.out.println("如果发生异常,该代码不会执行");

   }

调用该方法时,只会报错,不会有输出。
f1()调用有可能抛出异常的方法f2(),有3种情况:
情况一:f2()捕获处理异常(   最好
由于f2()处理了异常,所以异常就不会传播给调用f2()的函数(   异常一旦处理就不会再传播

publicclass test1{

   publicvoid testTry(){

      try{

         Integer.parseInt("d");

      }catch(Exception e){

         System.out.println("发生异常");

         return;

      }

   }

   publicstaticvoidmain(String[]args){

      test1 t = new test1();

      t.testTry();

      System.out.println("如果发生异常,该代码也会执行");

   }

}

情况二:f2()不对异常处理,f1()对异常处理

publicclass test1{

   publicvoid testTry()throws Exception {

         Integer.parseInt("d");

         System.out.println("如果发生异常,该代码不会处理");

   }

   publicstaticvoid main(String[]args){

      test1 t = new test1();

      try {

         t.testTry();

      } catch (Exception e) {

         System.out.println("发生异常");

      }

      System.out.println("如果发生异常,该代码也会执行");

   }

}

情况三:f1()、f2()都不对异常处理(   避免使用

publicclass test1{

   publicvoid testTry()throws Exception {

         Integer.parseInt("d");

         System.out.println("如果发生异常,该代码不会执行");

   }

   publicstaticvoid main(String[]args) throws Exception{

      test1 t = new test1();

      t.testTry();

      System.out.println("如果发生异常,该代码不会执行");

   }

}

运行时会报错


方法向外抛异常
让方法向外抛异常是为了让外部知道所调用的方法里面有异常,不能总利用return一个错误代号来告诉调用者所调用的方法发生异常,这样的话,返回结果与错误就混在一起了,而且调用者每次都要对返回的结果做一系列的判断,下面是一些常用的抛异常方法:
把捕获到的异常向外抛出:

publicclass test1{

   publicint testException(String i) throws Exception{

      try{

         return Integer.parseInt(i);

      }

      catch (Exception e) {

         throw e;

      }

   }

   publicstaticvoid main(String[]args){

      test1 test = new test1();

      try{

         test.testException("a");

      }

      catch (Exception e) {

         System.out.println(e);

      }

   }

}

简单地修改异常的输出:

publicclass test1{

   publicint testException(int i)throws Exception{

      if(i<0){

         thrownew Exception("i小于0");

      }

      return i;

   }

   publicstaticvoid main(String[]args){

      test1 test = new test1();

      try{

         test.testException(-5);

      }

      catch (Exception e) {

         System.out.println(e.getMessage());

      }

   }

}

输出:i小于0
自定义异常:

publicclass test1{

   publicint testException(int i) throws MyException{

      if(i<0){

         thrownew MyException("i小于0");

      }

      return i;

   }

   publicstaticvoid main(String[]args){

      test1 test = new test1();

      try{

         test.testException(-5);

      }

      catch (Exception e) {

         System.out.println(e.getMessage());

      }

   }

}

class MyException extends Exception{

   private String errorMessage = "";

   public MyException(String errorMessage){

      this.errorMessage = errorMessage;

   }

   @Override

   //重写getMessage方法

   public String getMessage(){

      returnerrorMessage;

   }

}

输出:i小于0


















版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://my.oschina.net/u/1987489/blog/491342

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值