Day28下1
异常机制
异常机制理解图
学习路线:
- 异常的概念
- 异常的出现原因
- 异常处理的机制
- 异常处理的能力
异常概念
异常是程序在运行期发生的不正常的事件,它会打断指令的正常执行流程。
设计良好的程序应该在异常发生时提供处理这些不正常事件的方法,使程序不会因为异常的发生而阻断或产生不可预见的结果。
Java语言使用异常处理机制为程序提供了异常处理的能力
异常分类
理解图
异常在Java中是以对象的形式表示的,这些对象是从java.lang.Throwable类或其子类派生而来。Throwable是异常类层次结构的根类,它有两个主要的子类:java.lang.Exception和java.lang.Error。
Java程序运行过程中所发生的异常事件从严重性可分为两类:
1、 错误(Error):
JVM系统内部错误或资源耗尽等严重情况-属于JVM需要负担的责任这一类异常事件无法恢复或不可能捕获,将导致应用程序中断。
public static void main(String[] args) {
//StackOverflowError - 栈内存溢出的错误
//出现原因:调用方法会在栈中开辟空间,用于存放该方法的局部变量,死循环的调用方法,栈内存就满载并溢出了
method();
}
public static void method(){
method();
}
对象占的空间过小也不会报错
//OutOfMemoryError -- 内存溢出的错误
//出现原因:new出来的数组添加到集合中,该数组不会被回收
ArrayList<byte[]> list = new ArrayList<>();
while(true){
byte[] bs = new byte[8192];
list.add(bs);
}
2、 异常(Exception):
其它因编程错误或偶然的外在因素导致的一般性问题。这类异常得到恰当的处理时,程序有机会恢复至正常运行状况。
分类:
RuntimeException – 非受检性异常
RuntimeException(非受检性异常):编译器不要求强制处置的异常。一般是指编程时的逻辑错误。是程序员应该积极避免其出现的异常。
注意:java.lang.RuntimeException及它的子类都是非受检异常
那么非运行时异常:程序员避免不了,由外界因素导致的
错误的类型转换:java.lang.ClassCastException
数组下标越界:java.lang.ArrayIndexOutOfBoundsException
空指针访问:java.lang.NullPointerException
算术异常(除0溢出):java.lang.ArithmeticException
//ArithmeticException -- 算数异常
System.out.println(10/0);
//ArrayIndexOutOfBoundsException -- 数组下标越界异常
int[] arr = {1,2,3};
System.out.println(arr[1000]);
//IndexOutOfBoundsException - 下标越界异常
ArrayList<Object> list = new ArrayList<>();
System.out.println(list.get(100));
public static void main(String[] args) {
//NullPointerException --空指针异常
String str = null;
method(str);
}
public static void method(String str) {
System.out.println(str.length());
}
//ClassCastException - 类型转换异常
Object obj = new Integer(100);
String str = (String) obj;
System.out.println(str);
一般性异常 – 受检性异常
一般性异常(受检性异常):编译器要求必须处置的异常。指的是程序在运行时由于外界因素造成的一般性异常。
理解:程序员避免不了,由外界因素导致的
没有找到指定名称的类:java.lang.ClassNotFoundException
访问不存在的文件:java.io.FileNotFoundException
操作文件时发生的异常:java.io.IOException
操作数据库时发生的异常:java.sql.SQLException
public static void main(String[] args) throws ClassNotFoundException {
//ClassNotFoundException -- 类未找到异常
Class<?> clazz = Class.forName("java.lang.String111111");
System.out.println(clazz);
}
public static void main(String[] args) throws FileNotFoundException {
//FileNotFoundException - 文件未找到异常
FileInputStream fis = new FileInputStream("C:\\Users\\奇男子\\Desktop\\异常理解图.png11111");
System.out.println(fis);
}
异常处理机制
1.Java程序在执行过程中如果出现异常,会自动生成一个异常类对象,该异常对象将被自动提交给JVM,这个过程称为抛出(throw)异常。
2.当JVM接收到异常对象时,会寻找能处理这一异常的代码
找到了 - 把当前异常对象交给其处理,这一过程称为捕获(catch)异常和处理异常。
没找到 - 运行时系统将终止,相应的Java程序也将退出。
Java处理异常的能力(方式)
1.try…catch…
语法结构:
try{
...可能出现异常的代码...
}catch(异常类型 e){//捕获异常
...处理异常...
}finally{
...不管是否发生异常,都会执行的代码块...
}
注意:
try 代码段后跟一个或多个catch代码段。(或跟一个finally代码段)
JDK新特性,一个catch代码可以可以声明多个能处理的特定异常的类型,多个类型之间用”|”隔开
例如:catch( ExceptionName1 | ExceptionName2 e){ ...... //异常的处理代码 }
写catch代码时,先捕获的异常的范围不能大于后捕获的异常的范围。大的异常要写在后面
finally段的代码无论是否发生异常都执行
1.finally代码块根据需求可写可不写
2.经验告诉我们关闭资源的代码一般写在finally
场景
注意:代码中的测试输出如:System.out.println(“111”);为了查看代码执行情况
有异常不会继续执行有异常的代码
处理异常后会继续向下进行
场景1:处理一个异常的情况
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个数字:");
int a = scan.nextInt();
System.out.println("请输入第二个数字:");
int b = scan.nextInt();
try{
System.out.println("111");
System.out.println(a/b);
System.out.println("222");
}catch (ArithmeticException e) {
System.out.println("处理算数异常");
}finally {
scan.close();
}
场景2:处理多个异常,但处理方式不一样的情况,注意范围大小
try 代码段后跟多个catch代码段
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个数字:");
int a = scan.nextInt();
System.out.println("请输入第二个数字:");
int b = scan.nextInt();
System.out.println("请输入类的全路径:");
String classPath = scan.next();
try{
System.out.println("111");
System.out.println(a/b);
System.out.println("222");
Class<?> clazz = Class.forName(classPath);
System.out.println(clazz.getName());
System.out.println("333");
}catch (ArithmeticException e) {
System.out.println("处理算数异常");
}catch (ClassNotFoundException e){
System.out.println("处理类未找到异常");
}finally {
scan.close();
}
多个类型之间用”|”隔开
try{
System.out.println("111");
System.out.println(a/b);
System.out.println("222");
Class<?> clazz = Class.forName(classPath);
System.out.println(clazz.getName());
System.out.println("333");
}catch (ArithmeticException | ClassNotFoundException e) {
System.out.println("处理异常");
}finally {
scan.close();
}
2.throws
在定义一个方法的时候可以使用throws关键字声明,使用throws声明的方法表示此方法不处理异常,而交给方法的调用出进行处理。
理解:
throws是抛出异常
抛给方法的调用方
语法结构:
注意:此时抛出的是异常类型,并且抛出的异常类型是紧跟在方法名之后。
public 返回值类型 方法名(参数列表) throws 异常类{
}
//可抛出多个异常
public void method() throws 异常1,异常2{}
场景
public static void main(String[] args) {
try {
method01();
} catch (ClassNotFoundException e) {
System.out.println("处理异常");
}
}
public static void method01() throws ClassNotFoundException{
method02();
}
public static void method02() throws ClassNotFoundException{
method03();
}
public static void method03() throws ClassNotFoundException{
Scanner scan = new Scanner(System.in);
System.out.println("请输入类的全路径:");
String classPath = scan.next();
Class<?> clazz = Class.forName(classPath);
System.out.println(clazz.getName());
scan.close();
}
3.throw
异常不仅仅虚拟机可以抛,我们自己也可以抛。我们可以在代码中使用throw关键字(注意不带s)来抛出某个具体的异常对象。很多情况下我们会手动抛出运行时异常。
理解:
手动抛出异常
throw 结合自定义异常使用
语法结构:
throw new 异常();
场景
public class Test01 {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("请输入一个数字:");
int a = scan.nextInt();
System.out.println("请输入第二个数字:");
int b = scan.nextInt();
try {
if(b == 0){
throw new MyException();
}
} catch (MyException e) {
b = 1;
System.out.println(e);
}
System.out.println(a/b);
scan.close();
}
}
public class MyException extends Exception{
@Override
public String toString() {
return "除数不能为0的异常";
}
}
自定义异常类
创建自定义异常
创建自定义异常,需要继承Exception 或其子类。
public class MyException extends Exception {
@Override
public String toString() {
// TODO Auto-generated method stub
return "我们自己的异常类";
}
}
使用自定义异常
解决业务需求上的问题
总结
标签:scan,处理,System,println,机制,异常,public,out From: https://blog.csdn.net/gangain/article/details/1367842202.异常
异常的概念
异常的分类
异常处理机制 – 面试题
异常处理的能力:
1.try…catch…
2.throws
3.throw