异常处理
目标
处理异常
明确什么是异常 (重点)能辨识出常见的异常及其含义。 (熟悉+)理解异常产生的原理 (了解)能处理异常 (重点)能够自定义异常类型 (熟悉)
什么是异常?
异常是在程序中导致程序中断运行的一种指令流。 例如,现在有如下的操作代码:
public class ExceptionDemo01{
public static void main(String argsp
[]){
int i
= 10 ;
int j
= 0 ;
System
.out
.println("============= 计算开始 =============") ;
int temp
= i
/ j
;
System
.out
.println("temp = " + temp
) ;
System
.out
.println("============= 计算结束 =============") ;
}
};
运行结果: ============= 计算开始 ============= Exception in thread “main” java.lang.ArithmeticException: / by zero at ExceptionDemo01.main(ExceptionDemo01.java:6) 以上的代码在“int temp = i / j ;”位置处产生了异常,一旦产生异常之后,异常之后的语句将不再执行了,所以现 在的程序并没有正确的执行完毕之后就退出了。 那么,为了保证程序出现异常之后仍然可以正确的执行完毕,所以要采用异常的处理机制。
处理异常
如果要想对异常进行处理,则必须采用标准的处理格式,处理格式语法如下: try{ // 有可能发生异常的代码段 }catch(异常类型1 对象名1){ // 异常的处理操作 }catch(异常类型2 对象名2){ try+catch的处理流程 finally 异常体系结构 // 异常的处理操作 } … finally{ // 异常的统一出口 }
try+catch的处理流程 1、 一旦产生异常,则系统会自动产生一个异常类的实例化对象。 2、 那么,此时如果异常发生在try语句,则会自动找到匹配的catch语句执行,如果没有在try语句中,则会将异常抛出. 3、 所有的catch根据方法的参数匹配异常类的实例化对象,如果匹配成功,则表示由此catch进行处理。
finally
在进行异常的处理之后,在异常的处理格式中还有一个finally语句,那么此语句将作为异常的统一出口,不管是否产生了异常,最终都要执行此段代码。
异常体系结构
异常指的是Exception , Exception类, 在Java中存在一个父类Throwable(可能的抛出) Throwable存在两个子类: 1.Error:表示的是错误,是JVM发出的错误操作,只能尽量避免,无法用代码处理。 2.Exception:一般表示所有程序中的错误,所以一般在程序中将进行try…catch的处理。 多异常捕获的注意点: 1、 捕获更粗的异常不能放在捕获更细的异常之前。 2、 如果为了方便,则可以将所有的异常都使用Exception进行捕获。 特殊的多异常捕获写法: catch(异常类型1 |异常类型2 对象名){ //表示此块用于处理异常类型1 和 异常类型2 的异常信息 }
throws关键字
在程序中异常的基本处理已经掌握了,但是随异常一起的还有一个称为throws关键字,此关键字主要在方法的声明上使 用,表示方法中不处理异常,而交给调用处处理。 格式: 返回值 方法名称()throws Exception{ }
throw关键字
throw关键字表示在程序中人为的抛出一个异常,因为从异常处理机制来看,所有的异常一旦产生之后,实际上抛出的就是一个异常类的实例化对象,那么此对象也可以由throw直接抛出。 代码: throw new Exception(“抛着玩的。”)
RuntimeExcepion与Exception的区别
注意观察如下方法的源码: Integer类: public static int parseInt(String text)throws NumberFormatException 此方法抛出了异常, 但是使用时却不需要进行try。。。catch捕获处理,原因: 因为NumberFormatException并不是Exception的直接子类,而是RuntimeException的子类,只要是 RuntimeException的子类,则表示程序在操作的时候可以不必使用try…catch进行处理,如果有异常发生,则由JVM进行处理。当然,也可以通过try catch处理。
自定义异常类 了解
编写一个类, 继承Exception,并重写一参构造方法 即可完成自定义受检异常类型。 编写一个类, 继承RuntimeExcepion,并重写一参构造方法 即可完成自定义运行时异常类型。 例如: class MyException extends Exception{ // 继承Exception,表示一个自定义异常类 public MyException(String msg){ super(msg) ; // 调用Exception中有一个参数的构造 } }; 自定义异常可以做很多事情, 例如: class MyException extends Exception{ public MyException(String msg){ super(msg) ; //在这里给维护人员发短信或邮件, 告知程序出现了BUG。 } };
异常处理常见面试题
1. try-catch-finally 中哪个部分可以省略?
答:
catch和
finally可以省略其中一个 ,
catch和
finally不能同时省略
注意
:格式上允许省略
catch块
, 但是发生异常时就不会捕获异常了
,我们在开发中也不会这样去写代码
.
2. try-catch-finally 中,如果
catch 中
return 了,
finally 还会执行吗?
答:
finally中的代码会执行
详解:
执行流程:
1. 先计算返回值, 并将返回值存储起来, 等待返回
2. 执行
finally代码块
3. 将之前存储的返回值, 返回出去;
需注意:
1. 返回值是在
finally运算之前就确定了,并且缓存了,不管
finally对该值做任何的改变,返回的值都不
会改变
2. finally代码中不建议包含
return,因为程序会在上述的流程中提前退出,也就是说返回的值不是
try或
catch中的值
3. 如果在
try或
catch中停止了JVM
,则
finally不会执行
.例如停电
- -, 或通过如下代码退出
JVM
:System
.exit(0);
例题:
快递柜
bean
package com
.java
.demo1
.bean
;
import java
.util
.Objects
;
public class Express {
private String id
;
private String company
;
private int code
;
public Express() {
}
public Express(String id
, String company
, int code
) {
this.id
= id
;
this.company
= company
;
this.code
= code
;
}
public String
getId() {
return id
;
}
public String
getCompany() {
return company
;
}
public int getCode() {
return code
;
}
public void setId(String id
) {
this.id
= id
;
}
public void setCompany(String company
) {
this.company
= company
;
}
public void setCode(int code
) {
this.code
= code
;
}
@Override
public String
toString() {
return "Express{" +
"id='" + id
+ '\'' +
", company='" + company
+ '\'' +
", code=" + code
+
'}';
}
@Override
public boolean equals(Object o
) {
if (this == o
) return true;
if (o
== null
|| getClass() != o
.getClass()) return false;
Express express
= (Express
) o
;
return Objects
.equals(id
, express
.id
);
}
@Override
public int hashCode() {
return Objects
.hash(id
);
}
}
dao
package com
.java
.demo1
.dao
;
import com
.java
.demo1
.bean
.Express
;
import java
.util
.Random
;
public class Dao {
private Express
[][] expresses
= new Express[10][10];
private int size
= 0;
private int x
;
private int y
;
public boolean insert(Express e
){
if(size
<100){
while(true){
x
= (int)(new Random().nextInt(10));
y
= (int)(new Random().nextInt(10));
if(expresses
[x
][y
]==null
){
expresses
[x
][y
] = e
;
size
++;
return true;
}
}
}
return false;
}
public boolean delete(Express e
){
for (int i
=0;i
<10;i
++){
for (int j
=0;j
<10;j
++){
if(expresses
[i
][j
]==e
){
expresses
[i
][j
] = null
;
size
--;
return true;
}
}
}
return false;
}
public boolean updata(Express e
,Express e2
){
for (int i
=0;i
<10;i
++){
for (int j
=0;j
<10;j
++){
if(expresses
[i
][j
]==e
){
expresses
[i
][j
] = e2
;
return true;
}
}
}
return false;
}
public Express
[][] getAll(){
return expresses
;
}
public Express
getByNumber(String number
){
Express e
= new Express();
e
.setId(number
);
for (int i
=0;i
<10;i
++){
for (int j
=0;j
<10;j
++){
if(e
.equals(expresses
[i
][j
])){
return expresses
[i
][j
];
}
}
}
return null
;
}
public Express
getByCode(int code
){
for (int i
=0;i
<10;i
++){
for (int j
=0;j
<10;j
++){
if(expresses
[i
][j
]!=null
){
if(expresses
[i
][j
].getCode()==code
){
return expresses
[i
][j
];
}
}
}
}
return null
;
}
public boolean size() {
if (size
==0){
return false;
}
return true;
}
}
main
package com
.java
.demo1
.main
;
import com
.java
.demo1
.bean
.Express
;
import com
.java
.demo1
.dao
.Dao
;
import com
.java
.demo1
.view
.Views
;
public class Main {
private static Dao dao
;
private static Views view
;
public static void main(String
[] args
){
init();
view
.start();
login();
view
.end();
}
public static void init(){
dao
= new Dao();
view
= new Views();
}
public static void login(){
o
:while(true){
int num
= -1;
num
= view
.login();
switch (num
){
case 0:
break o
;
case 1:
aindex();
break;
case 2:
uindex();
break;
default:
view
.choiceError();
break;
}
}
}
public static void aindex(){
p
:while(true){
int num
= -1;
num
= view
.aindex();
switch (num
){
case 0:
break p
;
case 1:
insert();
break;
case 2:
delete();
break;
case 3:
updata();
break;
case 4:
printAll();
break;
default:
view
.choiceError();
break;
}
}
}
public static void insert(){
Express e
= view
.insert();
if (dao
.getByNumber(e
.getId())!=null
) {
view
.youle();
} else {
if(dao
.insert(e
)){
view
.printInsert();
view
.printExpress(e
);
}else{
view
.insertError();
}
}
}
public static void delete(){
String id
= view
.delete();
Express e
= dao
.getByNumber(id
);
if(e
!=null
){
int yon
= view
.deleteConfirm();
switch (yon
){
case 1:
if(dao
.delete(e
)){
view
.printDelete();
view
.deleteCode(e
.getCode());
}else{
view
.deleteError();
}
break;
case 2:
break;
default:
view
.choiceError();
break;
}
}else{
view
.error();
}
}
public static void updata(){
String id
= view
.update();
Express e
= dao
.getByNumber(id
);
if(e
!=null
){
view
.printExpress(e
);
Express e2
= view
.newData();
if(dao
.updata(e
,e2
)){
view
.printUpdata();
view
.deleteCode(e
.getCode());
}else{
view
.updataError();
}
}else{
view
.error();
}
}
private static void printAll() {
Express
[][] expresses
= dao
.getAll();
if(dao
.size()){
view
.printAll(expresses
);
}else {
view
.nullExpress();
}
}
public static void uindex(){
q
:while(true){
int num
= view
.uindex();
switch (num
){
case 0:
break q
;
case 1:
int code
= view
.getExpress();
Express e
= dao
.getByCode(code
);
if(e
!=null
){
if(dao
.delete(e
)){
view
.printGet();
view
.deleteCode(e
.getCode());
}else{
view
.getError();
}
}else{
view
.error();
}
break;
default:
view
.choiceError();
break;
}
}
}
}
views
package com
.java
.demo1
.view
;
import com
.java
.demo1
.bean
.Express
;
import java
.util
.ArrayList
;
import java
.util
.List
;
import java
.util
.Random
;
import java
.util
.Scanner
;
public class Views {
private Scanner input
= new Scanner(System
.in
);
private Random rand
= new Random();
private List
<Integer> list
= new ArrayList<Integer>();
public void start(){
System
.out
.println("---欢迎使用---");
}
public void end(){
System
.out
.println("---感谢您的使用---");
System
.out
.println("-------再见-------");
}
public int input(){
while(true){
int num
= -1;
try {
num
= input
.nextInt();
return num
;
}catch(Exception e
){
System
.out
.println("请正确输入序号!!!");
input
.next();
}
}
}
public void printExpress(Express e
){
System
.out
.println("快递单号:"+e
.getId()+", 快递公司:"+e
.getCompany()+", 快递取件码:"+e
.getCode());
}
public void error(){
System
.out
.println("你输入的信息有误,快递不存在,请重新输入");
}
public void choiceError(){
System
.out
.println("你输入的选项有误,请重新输入");
}
public void nullExpress(){
System
.out
.println("当前快递库为空");
}
public int code(){
while(true){
int chongfu
= 0;
int code
= (int)(rand
.nextInt(900000)+100000);
for(int i
=0;i
<list
.size();i
++){
if(list
.get(i
)==code
){
chongfu
++;
}
}
if(chongfu
==0){
list
.add(code
);
return code
;
}
}
}
public int login(){
System
.out
.println("---请选择登陆用户---");
System
.out
.println("---1.管理员登录-----");
System
.out
.println("---2.用户登录-------");
System
.out
.println("---0.退出-----------");
return input();
}
public int aindex(){
System
.out
.println("---请选择要进行的操作---");
System
.out
.println("---1.快递录入----------");
System
.out
.println("---2.删除快递----------");
System
.out
.println("---3.修改快递----------");
System
.out
.println("---4.查看所有快递------");
System
.out
.println("---0.返回上级目录------");
return input();
}
public Express
insert(){
System
.out
.println("---请输入快递单号---");
String number
= input
.next();
System
.out
.println("---请输入快递公司---");
String company
= input
.next();
int code
= code();
Express e
= new Express();
e
.setId(number
);
e
.setCompany(company
);
e
.setCode(code
);
return e
;
}
public void youle(){
System
.out
.println("快递已存在");
}
public void printInsert(){
System
.out
.println("快递录入成功");
}
public void insertError(){
System
.out
.println("快递录入失败");
}
public String
delete(){
System
.out
.println("---请输入需要删除的快递单号---");
String number
= input
.next();
return number
;
}
public int deleteConfirm(){
System
.out
.println("---是否确认删除该快递---");
System
.out
.println("---1.是---------------");
System
.out
.println("---2.否---------------");
return input();
}
public void printDelete(){
System
.out
.println("快递删除成功");
}
public void deleteError(){
System
.out
.println("快递删除失败");
}
public String
update(){
System
.out
.println("---请输入需要修改的快递单号---");
String number
= input
.next();
return number
;
}
public Express
newData(){
System
.out
.println("---请输入新的快递单号---");
String number
= input
.next();
System
.out
.println("---请输入新的快递公司---");
String company
= input
.next();
int code
= code();
Express e
= new Express();
e
.setId(number
);
e
.setCompany(company
);
e
.setCode(code
);
return e
;
}
public void printUpdata(){
System
.out
.println("快递修改成功");
}
public void updataError(){
System
.out
.println("快递修改失败");
}
public void printAll(Express
[][] e
){
for(int i
=0;i
<10;i
++){
for(int j
=0;j
<10;j
++){
if(e
[i
][j
]!=null
){
printExpress(e
[i
][j
]);
}
}
}
}
public int uindex(){
System
.out
.println("---请选择要进行的操作---");
System
.out
.println("---1.快递取出----------");
System
.out
.println("---0.返回上级目录------");
return input();
}
public int getExpress(){
System
.out
.println("---请输入取件码---");
return input();
}
public void deleteCode(int code
){
list
.remove((Integer
) code
);
}
public void printGet(){
System
.out
.println("取件成功");
}
public void getError(){
System
.out
.println("取件失败");
}
}