文章目录
(1)异常机制的2种方式:throws, try…catch…
package 异常机制处理;
/**
* 处理异常有两种方式:
* 1.声明向上抛出 throws
* 2.捕捉 try....catch....
*
* 以下程序演示第一种方式:声明抛出,在方法声明的位置上使用throws关键字向上抛出异常
* */
import java.io.*;
public class ExceptionTest01 {
//public static void main(String[] args) throws FileNotFoundException {
//public static void main(String[] args) throws IOException {
public static void main(String[] args) throws Exception {
//创建文件输入流,读取文件
//思考:java编译器是如何知道以下的代码执行过程中可能出现异常。
//java编译器是如何知道这个异常发生的几率较高的呢?
//java编译器不是那么智能,因为FileInputStream这个构造方法在声明的位置上使用了throws FileNotFoundException;
FileInputStream fils=new FileInputStream("c:/ab.txt");
}
}
(2) 深入throws
package 异常机制处理;
/**
* 深入throws
* 子类与父类继承的关系或者说包含的关系 :FileNotFoundException < IOException < Exception
* */
import java.io.*;//导入其他包调用
public class ExceptionTest02 {
public static void main(String[] args) throws Exception {//main抛给jvm虚拟机
/*m1();
//使用throws处理异常不是真正处理异常而是推卸责任。虽然编译通过,但是hello运行不出来。
//谁调用的就抛给谁(向上抛)
//上面的m1方法如果出现了异常,因为采用的是上抛,给了JVM,JVM遇到这个异常就会退出JVM,下面的这个代码不会执行。
System.out.println("hello");//Exception in thread "main" java.io.FileNotFoundException: c:\ab.txt (系统找不到指定的文件。)
*/
//真正处理运用 try..catch...,就可以输出System.out.println("hello")
try {
m1();
}catch(Exception e) {}
System.out.println("hello");//hello
}
public static void m1() throws IOException {
m2();
}
public static void m2() throws FileNotFoundException{
m3();
}
public static void m3() throws FileNotFoundException{
new FileInputStream("c:/ab.txt");//FileInputStream构造方法声明位置上使用throws(向上抛)
}
}
(3) 方式2:try…catch
- 1.catch语句块可以写多个。
- 2.但是catch要从上到下,必须从小类型异常到大类型异常进行捕捉。
----(从小到大)FileNotFoundException < IOException < Exception - 3.try… catch…中最多执行一个catch语句块(其余的catch语句块不执行,但是必须写,为了处理其他异常),执行结束后try…catch…就结束了。
- 4.try语句块无异常,不执行catch 语句,但一般写catch语句,以防出现异常。
package 异常机制处理;
/**
* 处理异常的第二种方式:捕捉 ...try...catch...
* 语法:
* try{可能出现的异常代码;
* } catch (异常类型1 变量) {
* 处理异常代码;
* } catch (异常类型2 变量) {
* 处理异常代码;
* }.....
*
* */
import java.io.*;
public class ExceptionTest03 {
public static void main(String[] args) {
//以下代码编译无法通过,因为FileNotFoundException没有处理
/*try {
//FileNotFoundException
FileInputStream fis=new FileInputStream("c:/ba.txt");
}catch(ArithmeticException e) {//捕获的异常是算术异常,不是文件读取异常
}
*/
/* //编译通过
try {
//FileNotFoundException
FileInputStream fis=new FileInputStream("c:/ba.txt");
}catch(FileNotFoundException e) {//捕获文件读取异常
}
*/
/*//以下程序编译无法通过,因为还有更多IOException没有处理
try {
//FileNotFoundException
FileInputStream fis=new FileInputStream("c:/ba.txt");
fis.read();//IOException异常
}catch(FileNotFoundException e) {
}
*/
//程序编译通过
/*try {
//FileNotFoundException
FileInputStream fis=new FileInputStream("c:/ba.txt");
fis.read();
}catch(FileNotFoundException e) {
}catch(IOException e) {
}*/
//编译通过,IOException包含FileNotFoundException
/*try {
//FileNotFoundException
FileInputStream fis=new FileInputStream("c:/ba.txt");
fis.read();
}catch(IOException e) {
}
*/
//编译无法通过,catch语句可以写多个,但必须从上到下,从小到大捕捉
/*try {
//FileNotFoundException
FileInputStream fis=new FileInputStream("c:/ba.txt");
fis.read();
//两者顺序反过来了,catch从大到小编译不通过,
}catch(IOException e) {
}catch(FileNotFoundException e) {
}*/
}
}
(4) 深入try…catch…
注意:
(1)出现异常的语句,之后的语句不再执行(包括异常语句),从上到下执行第一个异常catch语句块;
(2)其余catch语句块不执行(处理其他异常句),但是必须写,否则其他异常句没有处理,编译不通过。
package 异常机制处理;
/**
* 结果:读取的文件不存在
* ABC
* */
import java.io.*;
public class ExceptionTest04 {
//编译无法通过
//IOException没有处理
/*public static void main(String[] args) throws FileNotFoundException {
FileInputStream fis=new FileInputStream("abc");
fis.read();
}*/
//编译通过
/*public static void main(String[] args) throws FileNotFoundException,IOException{
FileInputStream fis=new FileInputStream("abc");
fis.read();
}*/
//编译通过
/*public static void main(String[] args) throws IOException{
FileInputStream fis=new FileInputStream("abc");
fis.read();
}*/
public static void main(String[] args){
try{
//程序执行到此处发生了FileNotFoundException类型的异常。
//jvm会自动创建一个FileNotFoundException类型的对象,将该对象的内存地址赋值给catch语句块中的e变量
FileInputStream fis=new FileInputStream("abc");
/*上面的代码出现了异常,try语句块的代码不再继续执行(即不执行System.out.println("TTT");语句和fis.read();这个异常),
* 直接进入catch语句块中执行,从上往下执行第一个catch语句块
* try... catch...中最多执行一个catch语句块,执行结束后try...catch..就结束了
*/
System.out.println("TTT");
fis.read();
}catch(FileNotFoundException e) {//e内存地址指向堆中的那个对象是“FileNotFoundException类型的”事件
System.out.println("读取的文件不存在");
}catch(IOException e){//这个catch语句块虽然不执行,但是不能删除,是处理fis.read();,否则报错
System.out.println("其他IO异常");
}
System.out.println("ABC");
}
}
(5) getMessage和printStackTrace打印异常语句
package 异常机制处理;
/**
* 关于getMessage和printStackTrace方法的应用。
* */
import java.io.*;
public class ExceptionTest05 {
public static void main(String[] args) {
try {
FileInputStream fis=new FileInputStream("c:/ab.txt");
}catch(FileNotFoundException e) {
//打印异常堆栈信息
//一般情况下都会使用该方法去调试程序
e.printStackTrace();
/*
* java.io.FileNotFoundException: c:\ab.txt (系统找不到指定的文件。)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:110)
at 异常机制处理.ExceptionTest05.main(ExceptionTest05.java:11)
* */
String msg =e.getMessage();//这种调用方法比上面的printStackTrace方法简略
System.out.println(msg);//c:\ab.txt (系统找不到指定的文件。)
}
//这段代码会执行
System.out.println("ABC");
}
}
(6) try…catch…finally
package 异常机制处理;
/**
* 关于finally语句块
* 1.finally语句块可以直接和try语句块联用。try....finally....
* 2.try...catch...finally也可以
* 3.在finally语句块中的代码是一定会执行的
* */
import java.io.*;
public class ExceptionTest06 {
public static void main(String[] args) throws Exception {
/*try {
//此处不是异常语句
System.out.println("ABC");//ABC
return;
}finally {
System.out.println("Tset");//Test
} */
/*try {
FileInputStream fis=new FileInputStream("Test.java");
//上面语句块出现异常,下面不会执行
System.out.println("Hello");
}finally {
//会执行
System.out.println("AAAA");
}*/
//只要在执行finally语句块之前退出了JVM,则finally语句块不会执行。
try {
//退出JVM
System.exit(0);
}finally {
//不会执行
System.out.println("finally");
}
}
}
(7) 深入finally语句块
package 异常机制处理;
/**
* 结果:m1的i=11
* 10
* 深入finally语句块
* */
public class ExceptionTest07 {
public static void main(String[] args) {
int i=m1();
System.out.println(i);//10
}
public static int m1() {
int i=10;
try {
return i;
}finally {
i++;
System.out.println("m1的i="+i);//11
}
//m1方法的执行原理
/*public static int m1() {
int i=10;
try {
int temp=i;
return temp;
}
}finally {
i++;
System.out.println("m1的i="+i);//11
}*/
}
}
(8) finally语句块释放资源
package 异常机制处理;
/**
* finally语句块一定会执行,所以通常在程序中为了保证某资源一定会释放,所以一般在finally语句块中释放资源
* */
import java.io.*;
public class ExceptionTest08 {
public static void main(String[] args) {
//必须在外边声明,才能释放流
FileInputStream fis=null;
try{//语句正常,能找到文件,所以catch处理异常不执行
fis=new FileInputStream("ExceptionTest08.java");
//try语句块无异常,不执行catch 语句
}catch(FileNotFoundException e) {
e.printStackTrace();
}finally {
//为了保证资源一定会释放
if(fis!=null) {
try {
fis.close();//这是个异常,故下面catch(IOException e)处理
}catch(IOException e) {
e.printStackTrace();//输出异常
}
}
}
}
}
(9) 编译异常和运行异常
package 异常机制处理;
/**
*自定义“无效名字异常”。
*1.编译时异常,直接继承Exception
*2.运行时异常,直接继承RuntimeException
*/
public class ExceptionTest09 extends Exception {//编译时异常
//public class ExceptionTest09 extends RuntimeException {//运行时异常
//定义异常一般提供两个构造方法
public ExceptionTest09() {}
public ExceptionTest09(String msg) {
super (msg);
}
}
(10) 重写的方法不能比被重写的方法抛出更宽泛的异常
package 异常机制处理;
/*
* 重写的方法不能比被重写的方法抛出更宽泛的异常
* **/
import java.io.*;
/*
public class ExceptionTest10 {
public void m1() {}
}
class B extends ExceptionTest10 {
//子类永远无法抛出比父类更多的异常
public void m1() throws Exception()
}
*/
class ExceptionTest10{
//public void m1() throws FileNotFoundException{}
public void m1() throws IOException{}
}
class B extends ExceptionTest10{
//public void m1() throws IOException{}
public void m1() throws FileNotFoundException{}
}
(11) 异常例子
package 异常机制处理;
/**
* 模拟注册
* */
public class Test09 {
public static void main(String[] args) {
//假如用户提供的用户名如下:
//String username="jack";//这个有异常,结果是用户名的长度不能少于6位
String a="ajsjsaksja";//这个就是没有异常,结果是注册成功
//注册
CustomerService09 cs=new CustomerService09();
try {
//cs.register(username);
cs.register(a);
}catch(ExceptionTest09 e) {
System.out.println(e.getMessage());
}
}
}
package 异常机制处理;
//顾客相关的业务
public class CustomerService09 {
//对外提供一个注册的方法
public void register(String name) throws ExceptionTest09 {//手动创建的异常,想让外面程序知道,用throws
//完成注册
if(name.length()<6) {
//异常
//创建异常对象
//ExceptionTest09 e=new ExceptionTest09("用户名的长度不能少于6位");
//手动抛出异常
//throw e;
//连起来写,编译异常必须进行处理,throws或try..catch..
throw new ExceptionTest09("用户名的长度不能少于6位");
}
//如果代码能执行到此处,证明用户名是合法的
System.out.println("注册成功");
}
}