一,异常的概述
1,异常是什么?
A,异常模拟的是现实世界中华“不正常的”事件。
B,java中采用“类”去模拟异常。
C,类是可以创建对象的。
NullPointerException e=0x0012;
e 是引用类型, e中保存的是内存地址指向堆中的“对象”。
这个对象一定是NullPointerException类型。
这个对象就表示真实存在的异常事件,NullPointerException是一类异常。
2,异常机制的作用?
java语言为我们提供一种完善的异常处理机制。
作用是:程序发生异常事件之后,为我们输出详细的信息,程序员通过这个信息,可以
对程序进行一些处理。使程序更加健壮。
public class ExceptionTest{
public static void main(String[] args){
int a=10;
int b=0;
int c=a/b; //ArithMeticException 异常
//上面代码出现异常“没有处理”,下面的代码不会执行,直接退出JVM。
System.out.println("test语句");
/*
以上程序编译通过,但是运行时会出现异常,表示发生某个异常事件。
异常本质:程序执行过程中发生了算数异常这个事件,JVM为我们创建了一个
ArithMeticException类型对象。并且这个对象中包含了详细的异常信息,并且
JVM将这个对象中的信息输出到控制台。
*/
//异常处理机制使程序更加健壮
int a=10;
int b=0;
if(b!=a){
int c=a/b;
System.out.println(a+"/"+b+"="+c);
}else{
System.out.println("除数不能为0");
}
}
}
二,异常继承图
三,throws关键字声明异常
处理异常有两种方式:
1,声明抛出:throws
2,捕捉:try……catch……
以下演示是第一种方式:声明抛出,在方法声明的位置上使用throws关键字向上抛出异常。
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编译器是如何知道这个异常发生的概率比较高呢?
//因为FileIuputStream这个构造方法在声明的位置上使用了throws FileNotFoundException
FileIuputStream fis=new FileIuputStream("c : /ab.test");
以上程序没有使用throws抛出时,编译不能通过。
}
}
3,throws关键字深入
public class ExceptionTest02{
public static void main(String[] args) throws FileNotFoundException{
//m1();
//使用throws处理异常不是真正处理异常而是推卸责任,谁调用的就抛给谁。
//真正处理
try{
m1();
}catch(FileNotFoundException e){}
System.out.println("HelloWorld");
}
public static void m1() thorws FileNotFoundException{
m2();
}
public static void m2() thorws FileNotFoundException{
m3();
}
public static void m3() thorws FileNotFoundException{
new FileIuputStream("c : /ab.test");
//FileIuputStream构造方法声明位置上使用throws(向上抛)。
}
}
四,使用try……catch捕捉异常
语法:
try{
可能出现异常的代码
}catch(异常类型1 变量){
处理异常的代码
}catch(异常类型2 变量){
处理异常的代码
}…………
1,catch语句块可以写多个。
2,但是从上到下catch,必须从小类型异常到大类型异常进行捕捉。
3,try……catch……中最多执行一个catch语句块。执行结束之后try……catch……就结束了。
public class Exceptiontest03{
public static void main(String[] args){
/*
//以下代码编译不通过,因为FileNotFoundException没有处理
try{
//这里应该捕捉FileNotFoundException异常,但是捕捉了算数异常。
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
}catch(ArithmeticException e){
//捕捉的异常是算数异常
}
*/
//编译通过
/*
try{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
}catch(FileNotFoundException e){}
*/
//以下程序编译无法通过,因为还有更多IOException没有处理
/*
try{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
fis.read();
}catch(FileNotFoundException e){}
*/
//编译通过
/*
try{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
fis.read();
}catch(FileNotFoundException e){
}catch(IOException e){}
*/
//编译通过
/*
try{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
fis.read();
}catch(IOException e){}
*/
//编译无法通过
/*
//catch可以写多个,但是必须从上到下,从小到大捕捉
try{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
fis.read();
}catch(IOException e){
}catch(FileNotFoundException e){}
*/
}
}
public class ExceptionTest04{
//编译无法通过,IOException没有处理
/*
public static void main(String[] args) throw FileNotFoundException{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
fis.read();
}
*/
//编译通过
/*
public static void main(String[] args) throw FileNotFoundException{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
fis.read();
}
*/
public static void main(String[] args){
try{
//程序执行到此处发生了FileNotFoundException类型对象,JVM会自动创建一个
//FileNotFoundException类型的对象,将该对象的内存地址赋值给catch语句块中的 e 变量
FileIuputStream fis=new FileIuputStream("abc");
//上面的代码出现异常,try语句块的代码不执行,直接进入catch语句块中执行。
fis.read();
}catch(FileNotFoundException E){
//e内存地址指向堆中的那个对象是"FileNotFoundException类型的"事件。
System.out.println(e);//abc(系统找不到指定文件)
}catch(IOException e){
System.out.println("其他IO异常");
}
System.out.println("ABC");
}
}
五,关于getMessage和printStackTrace方法的应用
public class ExceptionTest05{
public static void main(String[] args){
try{
FileIuputStream fis=new FileIuputStream("c : /ab.txt");
}catch(FileNotFoundException e){
//e.printStackTream();//打印异常堆栈信息
//一般情况下都是这个方法区调试程序,打印信息比下面的方法更详细。
String mag=e.getMessage();//打印异常描述信息
System.out.println(mag);//(系统找不到指定文件)
}
System.out.println("ABC");
}
}
六,关于finally语句块
1,finally语句块可以直接和try语句块联用。try……finally……
2,try……catch……finally也可以
3,在finally语句块中的代码是一定会执行的。
public class ExceptionTest06{
public static void main(String[] args) throws Exception{
/*
try{
System.out.println("ABC");
return;
}finally{
System.out.println("test");
}
*/
try{
FileIuputStream fis=new FileIuputStream("Test.java");
//不会执行
System.out.println("tttttt");
}finally{
//会执行
System.out.println("finally语句块");
}
try{
//退出JVM,只有这种情况finally语句块才不会执行
System.exit(o);
}finally{
System.out.println(finally语句);
}
//只要在执行finally语句块之前退出JVM,否则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);
}
//以上代码执行原理
/*
int i=10;
try{
int temp=i;
return temp;
}finally{
i++;
System.ot.println("m1="+i);
}
*/
}
}
finally语句块是一定会执行的,所以通常在程序中为了保证某资源一定会释放,
所以一般在finally语句块中释放资源。
public class ExceptionTest08{
public static void main(String[] args){
//必须在外边声明
FileIuputStream fis=null;
try{
fis=new FileIuputStream("ExceptionTest08");
}catch(FileNotFoundException E){
e.printStackTrace();
}finally{
//为了保证某资源一定释放
if(fis!=null){
try{
fis.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
七,手动使用throws抛出异常
自定义“无效名字异常”。
1,编译时异常,直接继承Exception
2,运行时异常,直接继承RuntimeException
(1)
//编译时异常
public class IllegalNameException extends Exception{
//public class IllegalNameException extends RuntimeException{// 运行时异常}
//定义异常一般提供两个构造方法
public IllegalNameException(){}
public IllegalNameException(String msg){
super(msg);
}
}
(2)
//顾客相关业务
public class CustomerSercice{
//对外提供一个注册的方法
public void register(String name) throws IllegalNameException{
//完成注册
if(name.length()<6){
//异常
//创建异常对象
//IllegalNameException e=new IllegalNameException("用户名长度不能少于6位");
//手动抛出异常
//throw e;
throw new IllegalNameException("用户名不能少于6位");
}
//如果代码能执行到此处,证明用户名是合法的。
System.out.println("注册成功");
}
}
(3)
//模拟注册
public class Test{
public static void main(String[] args){
//假如用户提供的用户名如下
String username="khsadkhk";
//注册
CustomerSercice cs=new CustomerSercice();
try{
cs.register(username);
}catch(IllegalNameException e){
System.out.println(e.getMessage());
}
}
}
这(1)(2)(3)一起使用,创建在同一个包里面。
八,方法覆盖,方法重写的异常
class A{
public void m1(){}
}
class B extends A{
public void m2() throws Exception{}
//子类无法抛出比父类更多的异常
}
class A{
public void m1() throws IOException{}
}
class B extends A{
public void m1() throws FileNotFoundException
}