学java,先搞懂异常

Java的异常被分为两大类:Checked异常和Runtime异常(运行时异常)。所有的RuntimeException类及其子类的实例被称为Runtime异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常。
Java程序必须显式处理Checked异常,如果程序没有处理Checked异常,该程序在编译时就会发生错误,无法通过编译。
Runtime异常则更加灵活,Runtime异常无须显式声明抛出,如果程序需要捕获Runtime异常,也可以使用try...catch块来实现。
使用throws声明抛出异常时有一个限制,就是方法重写时“两小”中的一个规则,子类方法声明抛出的异常类型应该是父类方法声明抛出的异常类型的子类或相同,子类方法声明抛出的异常不允许比父类方法声明抛出的异常多。
在大部分时候推荐使用Runtime异常,而不使用Checked异常。尤其当程序需要自行抛出异常时,使用Runtime异常将更加简洁。
当使用Runtime异常时,程序无须在方法中声明抛出Checked异常,一旦发生了自定义错误,程序只管抛出Runtime异常即可。
如果程序需要在合适的地方捕获异常并对异常进行处理,则一样可以使用try...catch块来捕获Runtime异常。
在java的异常类体系中,Error和RuntimeException是非检查型异常,其他的都是检查型异常。
所有方法都可以在不声明throws的情况下抛出RuntimeException及其子类
不可以在不声明的情况下抛出非RuntimeException
简单的说,非RuntimeException要自己写catch块处理掉。
1.RuntimeException 首先看一段代码,主要内容就是将字符串类型的数字转化为整型的数字,然后让两个数字相乘,代码如下:

public class RuntimeException {public static void main(String[] args) { // TODO Auto-generated method stub String str="123"; int temp=Integer.parseInt(str); System.out.println(temp*temp); } }

查看parseInt方法的源代码如下:
public static int parseInt(String s) throws NumberFormatException { return parseInt(s,10); }

我们发现这个方法中抛出了NumberFormatException异常,但是在上面的代码中我们没有找到try...catch来处理,这是为什么呢。按照我们异常处理的知识,如果一个方法通过throws抛出了异常,那么可以在抛出异常的方法中不使用try...catch,但是在调用这个方法的地方必须有try...catch来处理。
下面来观察NumberFormatException类的继承关系:
学java,先搞懂异常
文章图片

从上图我们可以发现NumberFormatException是RuntimeException的子类,那么这就需要我们清楚Exception和RuntimeException的概念:
  1. Exception:在程序中必须使用try...catch进行处理。
  2. RuntimeException:可以不使用try...catch进行处理,但是如果有异常产生,则异常将由JVM进行处理。
对于RuntimeException的子类最好也使用异常处理机制。虽然RuntimeException的异常可以不使用try...catch进行处理,但是如果一旦发生异常,则肯定会导致程序中断执行,所以,为了保证程序在出错后依然可以执行,在开发代码时最好使用try...catch的异常处理机制进行处理。
2.User Defined Exception 下面给出一个自定义异常的实例:
class MyException extends Exception{ public MyException(String msg){ super(msg); } }public class DefaultException {/** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub try{ throw new MyException("自定义异常"); }catch(Exception e){ System.out.println(e); //edu.sjtu.ist.comutil.MyException: 自定义异常 //System.err.println(e); //e.printStackTrace(); //StackTraceElement[] sts = e.getStackTrace(); //for (StackTraceElement st : sts){ //System.err.println(st); //}//System.err.println(e.getStackTrace()); }}}

输出结果为:
MyException: 自定义异常

常见的RuntimeException 【学java,先搞懂异常】RuntimeException是开发中最容易遇到的,下面列举一下常见的RuntimeException:
1、NullPointerException:见的最多了,其实很简单,一般都是在null对象上调用方法了。
String s=null;
boolean eq=s.equals(""); // NullPointerException
这里你看的非常明白了,为什么一到程序中就晕呢?
public int getNumber(String str){
if(str.equals("A")) return 1;
else if(str.equals("B")) return 2;
}
这个方法就有可能抛出NullPointerException,我建议你主动抛出异常,因为代码一多,你可能又晕了。
public int getNumber(String str){
if(str==null) throw new NullPointerException("参数不能为空");
//你是否觉得明白多了

if(str.equals("A")) return 1;
else if(str.equals("B")) return 2;
}
2、NumberFormatException:继承IllegalArgumentException,字符串转换为数字时出现。比如int i= Integer.parseInt("ab3");
3、ArrayIndexOutOfBoundsException:数组越界。比如 int[] a=new int[3]; int b=a[3];
4、StringIndexOutOfBoundsException:字符串越界。比如 String s="hello"; char c=s.chatAt(6);
5、ClassCastException:类型转换错误。比如 Object obj=new Object(); String s=(String)obj;
6、UnsupportedOperationException:该操作不被支持。如果我们希望不支持这个方法,可以抛出这个异常。既然不支持还要这个干吗?有可能子类中不想支持父类中有的方法,可以直接抛出这个异常。
7、ArithmeticException:算术错误,典型的就是0作为除数的时候。
8、IllegalArgumentException:非法参数,在把字符串转换成数字的时候经常出现的一个异常,我们可以在自己的程序中好好利用这个异常。

    推荐阅读