java异常


Day01


  所有类的根父类是Object。
  枚举的公共父类是Enum,根父类仍然是Object
  异常的公共父类是Throwable,根父类仍然是Object


  1、异常的公共父类:java.lang.Throwable


  (1)只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java throw 语句“抛”出。
  (2)只有此类或其子类之一才可以是 catch 子句中的参数类型。 
  
  2、Throwable又分为两大派别:
  (1)Error:错误
       一般指严重错误,一般合理的应用程序不应该试图去捕获它。
       如果出现这个问题,要么需要升级程序,要么需要升级架构,要么需要升级硬件。
       例如:报了一个OutOfMemoryError、StackOverFlowError
 
       经典代表:VirtualMachineError(堆内存溢出OutOfMemoryError,栈内存溢出StackOverflowError)
  (2)Exception:异常(狭义上的异常)
       一般异常,合理的应用程序应该试图去捕获它。
  
  3、Exception还可以分为两大类:
  (1)运行时异常(RuntimeException或它子类):又称为非受检异常
       编译时,编译器是不会提醒你做处理的,只有运行期间,才会发生。
       运行时异常是不建议用try...catch,因为它发生频率太高,而且一般都是很不应该发生的问题。
       例如:空指针异常,数组下标越界异常,类型转换异常等,这些异常完全可以避免掉。
       但是如果实在没有考虑到,也可以通过try...catch处理。例如:数组下表越界,空指针异常、类型转换异常、算术异常
  
  (2)编译时异常,除了RuntimeException系列以外的,都是编译时异常。又称为受检异常。
       编译时,编译器会强制要求程序员编写处理的代码,如果你不编写,那么就编译不通过。
       例如:FileNotFoundException,IOException等

Day02

一、异常的处理方式:try...catch
  1、语法格式:
  try{
       可能发生异常的代码
  }catch(异常类型1  异常对象名){//异常对象名绝大多数都是写e
       处理这个异常的代码
  }catch(异常类型2  异常对象名){//异常对象名绝大多数都是写e
       处理这个异常的代码
  }catch(异常类型3  异常对象名){//异常对象名绝大多数都是写e
       处理这个异常的代码
  }
  。。。。
  
  2、异常对象的常用方法
  (1)e.printStackTrace();
  打印异常的详细信息,包括追踪跟踪信息,即这个异常对象一路经过了哪些方法
  (2)e.getMessage();
  返回异常对象中简单的错误信息提示
  
  3、打印异常/错误信息
  System.err.println(xx);打印错误信息
  
  System.out.println(xx);打印正常信息
  
  4、多个catch分支,如何匹配和执行的?
  从上到下依次判断,一旦有一个满足,后面就不看了。
  
  建议:如果多个catch中的异常类型有大小包含关系,那么小的在上,大的在下,如果没有大小包含关系,顺序随意。
  
  5、如果catch,可以捕获try中发生的异常,那么程序,会从try...catch下面的代码继续运行 ,不会崩溃。
   如果catch无法捕获try中发生的异常,那么就会导致当前方法结束,并把异常对象抛出调用者,
  如果调用者可以处理,那么从调用者处理代码的后面继续运行,否则继续往上抛,最终到达JVM,程序就崩溃了。

Day03

  二、try..catch的形式二
  try{
       可能发生异常的代码
  }catch(异常类型1  异常对象名){//异常对象名绝大多数都是写e
       处理这个异常的代码
  }catch(异常类型2  异常对象名){//异常对象名绝大多数都是写e
       处理这个异常的代码
  }catch(异常类型3  异常对象名){//异常对象名绝大多数都是写e
       处理这个异常的代码
  }
  。。。。
  finally{
       不管try中是否发生异常,也不管catch是否可以捕获异常,这里代码都必须执行
  }
  
  一般用于编写释放资源,断开连接等代码
  
  特殊情况:可以没有catch部分
  try{
       
  }finally{
       
  }

Day 04

finally与return混用:
 * (1)不管try中是否发生异常,也不管catch是否可以捕获异常,也无论try或catch中是否有return。
 *     finally中的代码都必须执行
 * (2)如果finally中有return,就从finally块的的return回去。
 * (3)如果finally中没有return,那么先把try或catch中该执行的执行完(包括把返回值的结果放到要带回调用处的操作数栈的位置)
 * 在return结束当前方法之前,先走一下finally,然后回去结束当前方法.
 * 结论,如果finally中没有return,finally中的代码不影响返回值。

public class test01 {
    public static void main(String[] args) {
        String num = getNum(1);
        System.out.println(num);
    }

    public static String getNum(int a){
        try {
            System.out.println(a/0);
            if(a>0){
                return "正数";
            }else if(a < 0){
                return "负数";
            }else {
                return "零";
            }
        }catch (Exception e){
            return "异常";
        }
    }
}

// 结果:
异常

原因:代码走到try模块中的第一行,即   "System.out.println(a/0);" ,就会发生异常,try模块中的后面代码不会执行,这时候要看catch能不能捕获异常,如果捕获到了,则则运行里面的代码。并继续执行main方法中的后续代码。所以最终会输出“异常”。

public class test01 {
    public static void main(String[] args) {
        String num = getNum(1);
        System.out.println(num);
    }

    public static String getNum(int a){
        try {
            System.out.println(a/0);
            if(a>0){
                return "正数";
            }else if(a < 0){
                return "负数";
            }else {
                return "零";
            }
        }catch (Exception e){
            return "异常";
        }finally {
            return "最终";
        }
    }
}

// 结果
最终

原因:不管try中是否会出现异常,都会走finally里面的return。所以会返回“最终”。

public class test01 {
    public static void main(String[] args) {
        String num = getNum(1);
        System.out.println(num);
    }

    public static String getNum(int a){
        try {
            System.out.println(a/0);
            if(a>0){
                return "正数";
            }else if(a < 0){
                return "负数";
            }else {
                return "零";
            }
        }catch (Exception e){
            return "异常";
        }finally {
            System.out.println("finally");
        }
    }
}

// 结果
exception
finally
异常

原因:try模块中出现异常,被catch抓住,先执行catch中的输出“exception”,但执行catch中的return之前,会先执行finally的语句,即先输出“finally”,然后再回到catch中的return语句,即输出“异常”。

public class test01 {
    public static void main(String[] args) {
        int num = getNum(4);
        System.out.println(num);
    }

    public static int getNum(int a){
        int result = 10;
        try {
            System.out.println(a/0);
            if(a>0){
                result = 20;
                return result;
            }else if(a < 0){
                result = -20;
                return result;
            }else {
                return result;
            }
        }catch (Exception e){
            System.out.println("exception");
            result = 0;
            return result;
        }finally {
            result = 30;
            System.out.println("finally");
        }
    }
}

// 结果
exception
finally
0

原因:try中有异常,被catch捕获,catch先输出“exception”,在执行reture语句之前先将0放到准备输出的地方,再去去执行finally中的语句,finally的对result赋值已经没用了,因为其本身没有return语句,所以他对result的更改不起作用,仅仅输出“finally”后就再一次返回到catch模块中,此时catch模块再将先前准备好的0,返回走。

若finally中也有return语句呢:

public class test01 {
    public static void main(String[] args) {
        int num = getNum(4);
        System.out.println(num);
    }

    public static int getNum(int a){
        int result = 10;
        try {
            System.out.println(a/0);
            if(a>0){
                result = 20;
                return result;
            }else if(a < 0){
                result = -20;
                return result;
            }else {
                return result;
            }
        }catch (Exception e){
            System.out.println("exception");
            result = 0;
            return result;
        }finally {
            result = 30;
            System.out.println("finally");
            return result;
        }
    }
}

// 结果
exception
finally
30

原因:和上一个比较起来,仅仅是finally中多了return语句,此时,catch中的return语句不管用了,即使先前准备好要输出的内容了,被finally的输出语句顶替了。这是finally对result的再一次赋值会起作用。所以会输出30.

/*
 * (1)finally里面有return,就从finally的return回去了
 * (2)类初始化:main所在的类要先初始化,才能执行main方法
 * 由①静态变量的显示赋值(这里没有)②静态代码块
 * (3)实例初始化:必须要new对象才会有,这里没有创建TestExer4的对象,所以不走
 *    
 *    
 *    结果:a
 *        3
 */
public class TestExer4 {
	{
		System.out.println("b");
	}
	static{
		System.out.println("a");
	}
	TestExer4(){
		System.out.println("c");
	}
	public static String getOut(){
		try{
			return "1";
		}catch(Exception e){
			return "2";
		}finally{
			return "3";
		}
	}
	public static void main(String[] args) {
		System.out.println(getOut());//3
	}
}

Day 5  throw

 

/**
 * throw
 *  语法格式:
 *      throw 异常对象;
 *  如果在某个方法中,用throw语句手动抛出异常,那么如果异常对象是运行时异常,那么没关系,方法不用加throws,
 *  如果是编译时异常(非运行时异常),方法还要加try...catch或throws
 *
 *  throw可以用于抛出“系统预定义异常”或“用户自定义异常”
 */

public class throwTest {
    public static void main(String[] args) {
        Account a = new Account(100);
        try {
            a.withdraw(-200);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            System.out.println("余额:" + a.getBalance());
        }
    }
}

class Account {
    private double balance;

    public Account(double balance) {
        super();
        this.balance = balance;
    }

    public boolean withdraw(double money) throws IllegalArgumentException, RuntimeException {
        if (money < 0) {
            //System.out.println("取款金额不能小于0");
            throw new IllegalArgumentException("取款金额" + money + "有问题,取款金额不能小于0");
        }
        if (money > balance) {
            throw new RuntimeException("余额不足");
        }
        balance -= money;
        return true;
    }

    public double getBalance() {
        return balance;
    }
}

Day 6 自定义异常

  自定义异常:
    如果系统预定义的异常类型,
       例如:ArrayIndexOutOfBoundsException
           ClassCastException
           NullPointerException
           ArithmeticException
           InputMisMatchException
           IllegalAugumentException
           ....
   发现不能准确的表达你当前的异常类型的意思时,你可以选择自定义。
  
  面试题:列出常见的异常类型,已经什么情况下会发生这个异常,你如何处理?
  至少5个
  
  
  1、自定义的要求:
  (1)必须继承Throwable或它的子类
  但是实际开发中,一般继承RuntimeException和Exception
  (2)建议大家保留两种构造器的形式
  ①无参构造
  ②带给父类的message属性赋值的构造器
  
  2、如何使用自定义异常
  只能使用throw语句进行手动抛出。它不能由JVM自动抛出。
  
  3、建议
  大家在自定义异常时,异常的类型名非常重要,见名知意。

public class TestDefine {
	public static void main(String[] args) {
		Account a = new Account(100);
		
		try {
			a.withdraw(-100);
		} catch (MoneyCannotNegativeException e) {
			System.out.println(e.getMessage());
			e.printStackTrace();
		}
	}
}

//例如:想要声明一个异常类型,表示金额不能为负数
class MoneyCannotNegativeException extends Exception{

	public MoneyCannotNegativeException() {
		super();
	}

	public MoneyCannotNegativeException(String message) {
		super(message);
	}
	
}

class Account{
	private double balance;
	
	public Account(double balance) {
		super();
		this.balance = balance;
	}

	public boolean withdraw(double money) throws MoneyCannotNegativeException{
		if(money < 0){
			throw new MoneyCannotNegativeException("取款金额" +money + "有问题,取款金额不能小于0");
		}
		if(money > balance){
			throw new RuntimeException("余额不足");
		}
		
		balance -= money;
		return true;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值