
1、异常的概念
第一,异常模拟的是现实世界中不正常的事件
第二,java中采用类的形式去模拟异常
第三,类是可以创建对象的
NullPointerException e = 0x1234,e是引用类型,e中保存的内存地址指向堆中的“对象”,个对象一定是NullPointerException类型,这个对象就表示真实存在的异常事件,NullPointerException是一类异常
抢劫时一类异常 --->类
张三被抢劫就是一类异常事件----->对象
异常机制的作用?
java语言为我们提供了一种完整的异常处理机制
作用是:程序发生异常事件为我们输出详细信息,程序员通过这个信息,可以对程序进行一些处理,使程序更加健壮
举个栗子:
public class Test{
// 入口
public static void main(String [] args) {
int a = 10;
int b = 0;
int c = a/b;
// 发生了异常实践,JVM向控制台输出以下信息
// Exception in thread "main" java.lang.ArithmeticException: / by zero
// at tranc.Test.main(Test.java:337)
// 本质:程序执行过程中发生了算数异常这个事件,JVM为我们创建了一个ArithmeticException类型的对象,婢妾这个对象包含了详细的异常信息,JVM将这个对象中的信息输出到控制台
}
}
2、异常的分类
编译时异常
运行时异常
继承关系如下图:

3、异常的捕获和处理
1、声明抛出 throws
2、捕捉 try...catch
举个栗子(声明抛出 throws)
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test{
// 入口
// 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 fis = new FileInputStream("c:/ab.txt"); // FileNoFoundException
}
}
举栗子(捕捉)
public class Test{
public static void main(String [] args) throws FileNotFoundException{
// try {
// m1();
// }catch(FileNotFoundException e){
// System.out.println("捕捉处理");
// }
m1();
// 使用throws处理异常不是真正的处理异常而是推卸责任
// 谁调用的就会抛给谁
// 上面的m1方法如果出现了异常,因为采用的是上抛,给了JVM,JVM遇到这个异常就会退出JVM,下面的代码不会执行
System.out.println("处理后");
}
public static void m1() throws FileNotFoundException {
m2();
}
public static void m2() throws FileNotFoundException {
m3();
}
public static void m3() throws FileNotFoundException {
new FileInputStream("c:/a.txt"); //FileInputStream构造方法声明位置上使用throws(向上)
}
}
JVM将该对象的信息打印在控制台上
并且JVM停掉了程序的运行
输出:
Exception in thread "main" java.io.FileNotFoundException: c:\a.txt (系统找不到指定的文件。)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
at tranc.Test.m3(Test.java:366)
at tranc.Test.m2(Test.java:363)
at tranc.Test.m1(Test.java:360)
at tranc.Test.main(Test.java:352)
4、如何取得异常对象具体信息:
关于getMessage和printStackTrace方法的应用
printStackTrace打印堆栈错误信息,比较详细
getMessage,只打印错误信息
public class Test01 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("c/a.txt");
}catch(FileNotFoundException e){
//打印异常堆栈信息
//一般情况下都会使用该方法去调用程序
e.printStackTrace();
/*
java.io.FileNotFoundException: c\a.txt (系统找不到指定的路径。)
at java.base/java.io.FileInputStream.open0(Native Method)
at java.base/java.io.FileInputStream.open(FileInputStream.java:219)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112)
at tranc.Test01.main(Test01.java:10) 、
*/
String msg = e.getMessage();
// System.out.println(msg);
// c\a.txt (系统找不到指定的路径。)
}
System.out.println("123");
}
}
5、关于finally语句快
1、finally语句块可以直接和try语句块连用。try....finally
2、try...catch...finally
3、在finally语句块中的代码一定会执行的
4、只要在执行finally语句块之前退出JVM,则finally语句块不会执行
5、finally语句块是一定要执行的,所以通常在程序中,为了保证某资源释放资源
public class Test{
public static void main(String [] args) throws FileNotFoundException{
// try {
// System.out.println(1);
// return;
// }finally{
// System.out.println(2);
// }
// 输出 1 2
// try {
// FileInputStream fis = new FileInputStream("Test.java");
//
// System.out.println(3);
// }finally {
// System.out.println(4);
// }
// 输出
// 4
// Exception in thread "main" java.io.FileNotFoundException: Test.java (系统找不到指定的文件。)
// 只要在执行finally语句块之前退出JVM,则finally语句块不会执行
// try {
// // 退出JVM
// System.exit(0);
// }finally {
// // 不会执行
// System.out.println("finally...");
// }
int i = m1();
System.out.println(i); // 10
}
public static int m1() {
int i = 10;
try {
return i;
}finally {
i++; //11
}
}
// 以上代码执行原理
// public static int m1() {
//
// int i = 10;
// try {
// int temp = i;
// return temp;
// }finally {
// i++;
// }
// }
}
再举一个栗子(finally释放资源)
public class Test{
public static void main(String [] args) throws FileNotFoundException{
// 必须在外边声明
FileInputStream fis = null;
try {
fis = new FileInputStream("a.java");
}catch(FileNotFoundException e) {
e.printStackTrace();
}finally {
// 为了保证资源一定释放
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
补充注意:
final:
用来修饰变量,修饰类,无法被继承,
final修饰的成员变量需要手动赋值
修饰的方法无法被覆盖,修饰的局部变量一旦赋值不可被改变
final和static连用的变量称为常量,常量全部大写。
finalize:
是object的方法的名字,垃圾回收器在回收前会自动调用java对象的finalize方法
finally
6、自定义异常
1、编译时异常,直接结成Exception
2、运行时异常RuntimeException
测试类:
public class Test{
public static void main(String[] args) {
String username = "jack1234";
Test01 t = new Test01();
try {
t.register(username);
} catch (Test e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
用户注册类:
public class CusterService{
public void register(String name) throws Test {
// 完成注册
if(name.length() < 6) {
// 异常
// 创建异常对象
// Test e = new Test("用户名长度不能小于6位");
// 手动抛出异常
// throw e;
throw new Test("用户名长度不能小于6位");
}
// 如果代码能执行到这,证明用用户名是合法的
System.out.println("注册成功");
}
}
自定义异常类:
public class UserException extends Exception{ // 编译时异常
public Test() {}
public Test(String msg) {
super(msg);
}
}
输出:
tranc.Test: 用户名长度不能小于6位
at tranc.Test01.register(Test01.java:19)
at tranc.Fox.main(Fox.java:9)
7、方法覆盖与异常
重写的方法不能比被重写的方法抛出更多的异常
子类不能比父类抛出更宽泛的异常
举栗子:
public class Test{ // 编译时异常
public void m1() {};
}
public B extends A{
// 子类永远也无法抛出比父类更多的异常
public void m1() throws Exception{}
}
再举个栗子:
class Test {
public void m1() throws FileNotFoundException{};
}
class B extends Test{
// 子类不能比父类抛出更宽泛的异常
public void m1() throws IoException{}
}
网友评论