异常的概念
异常的英文单词是exception,字面翻译就是“意外、例外”的意思,也就是非正常情况。java异常是java提供的用于处理程序中错误的一种机制。所谓错误是指在程序运行的过程中发生的一些异常事件;事实上,异常本质上是程序上的错误。
10.2 异常的分类
异常主要分为运行时异常和非运行时异常:
运行时异常都是Unexceptionably类及其子类异常,如Interception、Unexceptionably等, 这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的, 程序应该从逻辑角度尽可能避免这类异常的发生。
非运行时异常是Unexceptionably以外的异常。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如Conception、Exceptional等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
10.3 异常体系结构
1.Error:称为错误,由Java虚拟机生成并抛出,包括动态链接失败,虚拟机错误等,程序对其不做处理。
2.Exception:所有异常类的父类,其子类对应了各种各样的可能出现的异常事件,一般需要用户显示的声明或捕获。
3.0Runtime Exception:一类特殊的异常,如被0除、数组下标超范围等,其产生比较频繁,处理麻烦,如果显示的声明或捕获将会对程序可读性和运行效率影响很大。因此由系统自动检测并将它们交给缺省的异常处理程序(用户可不必对其处理)。
其实异常部分主要讲的就是五个关键字:try、catch、finally、throw、throws:
1.try语句:
try{……}语句制定了一段代码,这段代码就是一次捕获并处理例外的范围。在执行过程中,该段代码可能会产生并抛出一种或几种类型的异常对象,它后面的catch语句要分别对这些异常做相应的处理。如果没有例外发生,所有的catch代码段都被略过不执行。
2.catch语句:
在catch语句块中是对异常进行处理的代码,每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常对象。
在catch中声明的异常对象(catch(Exception e))封装了异常事件发生的信息,在catch语句块中可以使用这个对象的一些方法获取这些信息。
3.finally语句:
finally语句为异常处理提供一个统一的出口,使得在控制流程转到程序的其他部分以前,能够对程序的状态做统一的管理。
无论try所指定的程序块中是否抛出例外,finally所指定的代码都要执行。
通常在finally语句中可以进行资源的清除工作,如:
1)关闭打开的文件
2)删除临时文件
3)……
**4.throws语句:
throws关键字的最大好处是:在方法中不处理任何的异常,而交给被调用处处理。
5.throw语句:
在程序中可以使用throw关键字人为的抛出一个异常。在异常处理中,实际上每次产生异常的时候都是产生了一个异常类的实例化对象。那么此时,也可以通过抛出异常对象的方式完成。**
10.4 常见的异常和解决方式
下面就看一下常见的一些异常和处理:
示例(封装类):
package com.ambow.test;
/**
* 玩家封装数据
*
* */
public class Player {
private int id;//表示玩家的编号
private String loginname;//表示玩家用户名
private String password;//表示密码
private String nickname;//表示玩家昵称
private String sex;//表示玩家性别
private int age;//表示玩家年龄
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
示例:
package com.ambow.test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class ExceptionDemo {
public void say(Player pla){
}
/*
*异常的概念:本质上就是程序的错误
*异常的分类:1.运行时异常 exception:程序运行时发生的异常,可以不处理,要尽量避免
* 2.非运行时异常error:可以在编译期被检测到,必须要处理
* 常见的异常:
* 1.数组下标越界异常
* 2.空指针异常
* 3.算术异常
* 4.输入不匹配异常
* 5.类型转换异常
* 6.解析异常
* 7.类路径丢失异常
* 8.参数类型不匹配异常
* */
public static void main(String[] args) throws ParseException, ClassNotFoundException {
//java.lang.ArrayIndexOutOfBoundsException:数组下标越界异常
//解决方案:查看数组的下标是否有异常
/*int[] ints=new int[10];
ints[10]=5;*/
//java.lang.NullPointerException:空指针异常
//解决方案:查看你的赋值(引用,对象)或者传值(引用,对象)是否丢失
/*Player pla=null;
System.out.println(pla.getLoginname());*/
//java.lang.ArithmeticException:算术异常
//解决方案:说明的你的数学逻辑出问题,将其修改就可以
//System.out.println(100/0);
//java.util.InputMismatchException:输入不匹配异常
//解决方案:使用异常的处理
/*Scanner sc=new Scanner(System.in);
System.out.println("请输入一个数字:");
sc.nextInt();*/
//多态
/*Object o=new Integer(5);
System.out.println(o);
//java.lang.ClassCastException:类型转换异常
//解决方案:后面说。。。。
String s=(String)o;
System.out.println(s);*/
/*SimpleDateFormat sf=new SimpleDateFormat("yyyy/MM/dd");
//java.text.ParseException:解析异常
//解决方案:查看解析的格式是否一致
Date date=sf.parse("2018-07-16");
System.out.println(date);*/
//java.lang.ClassNotFoundException:类路径丢失异常
//Class.forName("com/tjzs/a/ExceptionDemo.java");
//java.lang.lllegalArgumentException:参数类型不匹配异常
//解决方案:参看传递的参数是否与定义的参数一致
}
}
10.5 异常的执行原理
执行try时,如果发生异常。JVM会自动创建一个相应类型的异常对象。然后catch块会检查异常的类型,如果发生的异常恰恰和catch观察的类型一样,则由相应的catch处理该异常。所以,catch块可以有多个,并且按照从前往后的顺序检查。一般把小的异常类型放在前面,大的类型(Exception)放到后面
10.6 异常的处理
异常的处理主要包括捕捉异常、程序流程的跳转和异常处理语句块的定义等。
在Java程序里,异常对象是依靠try/catch语句来捕捉和处理的。
try{
…… //try语句块,可能产生异常情况
}catch(异常类型 异常对象){
…… //catch语句块,对异常进行处理
}finally{
… //无论是否有异常出现,都必须执行
}
在try块之后,可能有许多catch块,每一个都处理不同的异常.finally语句只用来控制从try—catch语句转移到另一部分前的一些必要的善后工作,这些工作包含了关闭文件或释放其他有关系统资源。finally语句执行的是一种强制的无条件执行,即无论在程序中是否出现异常,也不管出现的是哪一种异常,即使try代码块中包含有break、continue、return或者throw语句,都必须执行finally块中所包含的语句。
10.5.1 异常的捕获
异常捕获的基本思想:
当一个异常被抛出时,应该有专门的语句来捕获这个被抛出的异常对象,这个过程被称为捕捉异常。
Java的异常处理是通过3个关键词来实现的:try-catch-finally。用try来执行一段程序,如果出现异常,系统抛出(throws)一个异常,可以通过它的类型来捕捉(catch)并处理它,最后一步是通过finally语句为异常处理提供一个统一的出口,finally所指定的代码都要被执行(catch语句可有多条;finally语句最多只能有一条,根据自己的需要可要可不要)。
异常捕获的语法:
try{
可能出现异常的语句
}catch(异常类 异常对象){
异常处理
}catch(异常类 异常对象){
异常处理
}
…
finally{
异常的出口;
}
示例:
package com.ambow.test;
/**
* 处理异常的方式:
* 1.try-catch模块(异常的处理)
* 2.通过throws关键字来抛出异常(异常的抛出)
* */
public class ExcptionDemo2 {
/*try-catch的语法格式:
* 一个try后面可以跟多个catch语句,也就是说一个try语句中可以捕获多个异常,
* 但是在具体执行时只会捕获出现的第一个异常
* try{
* //可能出现异常的语句
* retrun;
* }catch(Excption e1){
* //异常的信息 e.。。。。。
* //处理异常的代码
* }catch(Excption e2){
* //异常的信息 e.。。。。。
* //处理异常的代码
* }.....
* finally{
* //不管你有没有异常都会执行finally中的语句块,但是finally语句块不是必须的,可以不写
* **加了finally语句块,只要try开始执行,即使遇到retrun,finally仍然执行**
* }
* */
public static void main(String[] args) {
try{
Player pla=null;
System.out.println(pla.getLoginname());
System.out.println(100/0);
System.out.println("123");
return;
}catch(NullPointerException e){
//用来告诉我们出现了什么异常,它是爆红的
//e.printStackTrace();
System.out.println("出现了空指针异常");
}catch(ArithmeticException e){
//用来告诉我们出现了什么异常,它是爆红的
//e.printStackTrace();
System.out.println("出现了算术异常");
}finally{
System.out.println("不管有没有异常我都会执行");
}
}
10.5.2 异常的抛出
异常抛出的基本思想:
Java应用程序在运行时如果出现了一个可识别的错误,就会产生一个与该错误相对应的异常类的对象,这个对象包含了异常的类型和错误出现时程序所处的状态信息,这个异常对象首先被交给Java虚拟机,由虚拟机来寻找具体的异常处理者。在Java中把产生异常对象并将其交给Java虚机的过程称为称为异常的抛出。
异常抛出的方式:
1.throws:throws一般出现在方法声明上,代表方法可能出现的异常。throws只是一个声明,告诉方法的调用者,调用该方法时需要处理某种或某几种异常 。真的发生异常时,方法本身可以不处理,而是由方法的调用者处理。throws可以声明多种类型异常。
2.throw:我们只需要创建相应类型的异常对象,然后通过throw(抛出)异常,就能触发一个异常,该种抛出异常的方式比较直接。
示例(throws):
package com.ambow.test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
/**
* 处理异常的方式:
* 1.try-catch模块(异常的处理)
* 2.通过throws关键字来抛出异常(异常的抛出)
*
* */
public class ExcptionDemo2 {
public static void main(String[] args) {
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
try {
sf.parse("2018/07/16");
} catch (ParseException e) {
// 提示我们异常出现在哪一行
e.printStackTrace();
System.out.println("出现了解析异常");
}
ExcptionDemo2 ee=new ExcptionDemo2();
try {
//调用将异常抛在方法上的方法时,需要抛异常,因为throws只是一个声明
//throws声明告诉方法调用者,调用该方法是需要处理某种或者多种异常
ee.method();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void method() throws ParseException{
SimpleDateFormat sf=new SimpleDateFormat("yyyy-MM-dd");
sf.parse("2018/07/16");
}
}
示例(throw):
if(age < 0){
throw new Exceptional("年龄不能为负数!");
}
10.5.3 throw和throws的区别
1.throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在住函数中调用该方法时,如果发生异常,就会将异常抛给指定异常对象。
2.throw关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw语句时立即停止,它后面的语句都不执行。通常throw抛出异常后,如果想在上一级代码中来捕获并处理异常,则需要在抛出异常的方法中使用throws关键字在方法声明中指明要抛出的异常;如果要捕获throw抛出的异常,则必须使用try{}catch{}语句。
10.5.4 自定义异常
可以通过继承Exception类,创建自定义的异常类型。自定义异常,可以用来处理业务逻辑上的错误,重写getMessage或者其它方法,来设置message属性值,从而设置自定义异常的输出信息。
示例(自定义异常类):
package com.ambow.test;
/**
* 1.自定义异常类
* 2.继承Exception类
* 3.创建有参构造函数并且调用父类中的有参构造函数
* */
public class BankException extends Exception {
public BankException(String message){
super(message);
}
}
示例(使用):
package com.ambow.test;
public class Bank {
//定义银行卡的余额
private double blance;
public double getBlance() {
return blance;
}
public void setBlance(double blance) {
this.blance = blance;
}
//存款方法
public double add(double money){
return this.blance+=money;
}
//取款方法
public double sub(double money) throws BankException{
if(this.blance-money>=0){
this.blance-=money;
}else{
throw new BankException("余额不足");
}
return this.blance;
}
}
示例(测试):
package com.ambow.test;
public class Test {
public static void main(String[] args) throws BankException {
Bank b=new Bank();
b.setBlance(5000);
double d=b.add(3000);
System.out.println("存入3000元以后的余额为:"+d);
d=b.sub(9000);
System.out.println("取入9000元以后的余额为:"+d);
}
}
示例结果:
说明:通过throw在方法内部抛出一个自定义异常。显示信息,就是Message的内容;方法内部抛出异常后,本身不处理,通过throws声明。方法调用者,同时处理方法的异常
异常
异常的分类
常见异常
异常的处理方式:
捕获 try-catch-finally
抛出 throws
自定义异常 throw