Java异常处理

一. 异常分类

Throwable 类是Java所有异常和错误的基类,其子类分为两大类,分别是异常(Exception)和错误(Error)

Exception

非致命异常。程序可处理。分为受编译器检测的checked异常(受检异常)和不受编译器检测的unchecked异常(非受检异常)。

  1. checked exceptions

    • 非运行时异常 (编译异常)

    • 编译器会强制在编译时对异常进行捕获或声明,可以用try-catch捕获

    • 如:IOException,SQLException等

  2. unchecked exceptions

    • 运行时异常,RuntimeException 类及其子类异常
    • 测试时程序终止,控制台出现异常,不建议捕获
    • 如:NullPointerException,IndexOutOfBoundsException等
RunTimeException
  1. ArithmeticException 类
public class Test {
	public static void main(String[] args) {
		try{
            int a,b,c;
            a=1;
            b=0;
            c=a/b;
            System.out.println(c);
		}
        catch(ArithmeticException ae){
            ae.printStackTrace(); 
            System.out.println("算术异常");
        }
	}
}
  1. NullPointerException 类
public class Test {
	private static int[] x;
	public static void main(String[] args) {
		try {
			System.out.println(x[0]);
		}
		catch(NullPointerException ne) {
            ne.printStackTrace(); 
            System.out.println("空指针异常");
		}
	}
}
  1. ArrayIndexOutOfBoundsException 类
public class Test {
	public static void main(String[] args) {
		try{
			String foo=args[1];
			System.out.println("foo="+foo);
		}
		catch(ArrayIndexOutOfBoundsException ae) {
            ae.printStackTrace(); 
            System.out.println("数组下标越界");
		}
	}
}
  1. ClassCastException 类
class Father{}
class Son extends Father{}
public class Test{
    public static void main(String args[]){
        try{
            Father father = new Father();
            Son son = (Son) father;

        }
        catch(ClassCastException ce){
            ce.printStackTrace();
            System.out.println("类型强制转换异常");
        }
    }
}
  1. NegativeArraySizeException 类
public class Test {
    public static void main(String[] args) {
        try{
            int[] a;
            a=new int[-1];
        }
        catch(NegativeArraySizeException ne) {
            ne.printStackTrace();
            System.out.println("数组下标负数异常");
        }
    }
}

Error

致命异常。标识系统发生了不可控的错误。程序无法处理,只能人工介入。

  • 由Java虚拟机生成并抛出,程序基本不可以通过后续代码修复,从而理应终止
  • 如:VirtualMachineError,ThreadDeath等
StackOverflowError

栈溢出,虚拟机栈或本地方栈空间被耗尽,没有足够资源分配给新创建的栈帧

  1. 原因:
    • 递归调用过深,没有跳出递归的条件
    • 执行了大量方法,导致线程栈空间耗尽
    • 不断创建线程
  2. 解决方法:
    • 减少递归层数或调用方法层次
    • 手动修改栈大小
OutOfMemoryError

内存溢出,程序运行过程中申请的内存大于系统能够提供的内存,导致无法申请到足够的内存

  1. 原因:
    • 内存泄漏
    • 在比较深的循环中创建对象
    • 静态变量过多
  2. 解决方法:
    • 减小内存申请空间
    • 手动修改内存空间(栈或堆)大小参数,调整虚拟机启动参数

二. 异常处理

声明抛出处理

向调用方传播异常,自身不处理

  1. 显示声明抛出,throws语句
public class ExampleException  {
   public static void main(String[] args) throws ArithmeticException{
       int a,b,c;
       a=67; b=0;
       c=a/b;
       System.out.println(a+"/"+b+"="+c);
   }
}
/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at ExampleException.main(ExampleException.java:6)
*/
  1. 隐式声明抛出,若是unchecked异常类型,则throws声明子句可省略
public class Test  {
    private static int[] x;
    public  static void main(String[] args){
        System.out.println(x[0]);
    }
}
/*
Exception in thread "main" java.lang.NullPointerException
	at Test.main(Test.java:4)
*/

程序捕获处理

在当前方法捕获并处理异常

  1. try-catch-finally语句
public class Test  {
    public static int method() { // throws ArithmeticException 语句省略
        int a,b,c;
        a=67; b=0;
        c=a/b;
        return c;
    }
    public static void main(String[] args) {
        try {
            System.out.println(method());
        }
        catch(ArithmeticException ae){
            ae.printStackTrace();  	
            System.out.println("Arithmetic Error!");
        }
        finally {
            System.out.println( "Finally" );
        }
    }
}
/*
	java.lang.ArithmeticException: / by zero
		at Test.method(Test.java:5)
		at Test.main(Test.java:10)
	Arithmetic Error!
	Finally
*/
  • finally 语句(可选)
    • 作用:一般用来进行一些善后清理操作,例如清理资源、释放连接、关闭文件、管道流等操作。

三. throws vs throw

throws

函数方法抛出异常,一般写在方法的头部,用来抛出一些异常,本身不进行解决,抛给方法的调用者进行解决(try-catch)

class Example{
    int a=25;
    int b=0;
    int c;
    public int method() throws ArithmeticException{
        c=a/b;
        return c;
    }
}
public class Test {
    public static void main(String[] args){
        Example ex = new Example();
        try{
            System.out.println(ex.method());
        }
        catch(ArithmeticException ae){
            ae.printStackTrace();
        }
    }
}
/*
	java.lang.ArithmeticException: / by zero
		at Example.method(Test.java:6)
		at Test.main(Test.java:15)
*/

throw

语句抛出异常,出现于函数内部,用来抛出一个具体异常实例,throw被执行后,后面的语句不起作用,直接转入异常处理阶段

class Example{
    int a=25;
    int b=0;
    int c;
    public void method(){
        c=a/b;
    }
}
public class Test {
    public static void main(String[] args){
        Example ex = new Example();
        try{
            ex.method();
            throw new ArithmeticException();
             //System.out.println("Try"); java: 无法访问的语句
        }
        catch(ArithmeticException ae){
            ae.printStackTrace();
        }
    }
}
/*
	java.lang.ArithmeticException: / by zero
		at Example.method(Test.java:6)
		at Test.main(Test.java:14)
*/

四. 自定义异常类应用

class SelfException extends Exception {
    private int id;

    public SelfException(String msg, int id) {
        super(msg);
        this.id = id;//调用Exception的构造方法
    }

   	public int getId() {
        return id;
    }
}
public class Test{
    public static void checkId(int id) throws SelfException{
        if(id < 0){
            throw new SelfException("id不能为负值", id);
        }else if(id>1500){
            throw new SelfException("id超出范围", id);
        }else{
            System.out.println("id正确");
        }
    }

    public static void main(String args[]){
        try{
            checkId(10000);
        }
        catch(SelfException se){
            se.printStackTrace();
            System.out.println("id=" + se.getId() + " 不正确");
        }
    }
}
/*
	SelfException: id超出范围
		at Test.checkId(Test.java:19)
		at Test.main(Test.java:27)
	id=10000不正确
*/

总结

​ 从简单认识异常分类到对异常进行捕获并处理的应用逐渐了解Java异常处理机制,通过对异常的处理,可以使程序更为完善,考虑到尽可能多的特殊情况,增强容错率,是以后软件开发中不可缺少的环节

​ 在整理博客的过程中参考了一些资料以及许多他人优秀的文章,就不一一列举,在此表示感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值