共计 8696 个字符,预计需要花费 22 分钟才能阅读完成。
疾速入门
将可能出现异常的代码块选中 -> 快捷键 ctrl + alt + t
-> 选中 try-catch
package com.hspedu.exception_;
public class Exception01 {public static void main(String[] args) {
int num1 = 10;
int num2 = 0;//Scanner();
//2. 当执行到 num1 / num2 因为 num2 = 0, 程序就会呈现 (抛出) 异样 ArithmeticException
//3. 当抛出异样后,程序就退出,解体了, 上面的代码就不再执行
//4. 不应该呈现了一个不算致命的问题就导致整个零碎解体
//5. java 设计者,提供了一个叫异样解决机制来解决该问题
// 如果程序员,认为一段代码可能出现异常 / 问题,能够应用 try-catch 异样解决机制来解决,从而保障程序的健壮性
// 将该代码块 -> 选中 -> 快捷键 ctrl + alt + t -> 选中 try-catch
//6. 如果进行异样解决,那么即便呈现了异样,程序能够继续执行
try {int res = num1 / num2;} catch (Exception e) {//e.printStackTrace();
System.out.println("出现异常的起因 =" + e.getMessage());// 输入异样信息
}
System.out.println("程序持续运行....");
}
}
异样介绍
Java 语言中,将程序执行中产生的不失常状况称为“异样”。(开发过程中的语法错误和逻辑谬误不是异样)
执行过程中所产生的异样事件可分为两大类:
1.Error(谬误):Java 虚拟机无奈解决的重大问题。如:JVM 零碎外部谬误、资源耗尽等重大状况。比方: StackOverflowError[栈溢出] 和 OOM(out of memory).
Error 是严重错误, 程序会解体。
2.Exception: 其它因编程谬误或偶尔的外在因素导致的一般性问题,能够应用针对性的代码进行解决。例如空指针拜访,试图读取不存在的文件,网络连接中断等等,Exception 分为两大类:
- 运行时异样[程序运行时,产生的异样]
- 编译时异样[编程时, 编译器查看出的异样]
异样体系图一览!
异样体系图
异样体系图的小结
- 异样分为两大类,运行时异样和编译时异样.
- 运行时异样,编译器查看不进去。个别是指编程时的逻辑谬误,是程序员应该防止其呈现的异样。
java.lang.RuntimeException
类及它的子类都是运行时异样。 - 对于运行时异样,能够不作解决,因为这类异样很广泛,若全解决可能会对程序的可读性和运行效率产生影响。
- 编译时异样,是编译器要求必须处理的异样。
常见的运行时异样
常见的运行时异样包含
1) NullPointerException
空指针异样
2) ArithmeticException
数学运算异样
3) ArrayIndexOutOfBoundsException
数组下标越界异样
4) ClassCastException
类型转换异样
5) NumberFormatException
数字格局不正确异样[]
常见的运行时异样举例
-
NullPointerException
空指针异样
当应用程序试图在须要对象的中央应用 null 时,抛出该异样。public class NullPointerException_ {public static void main(String[] args) { String name = null; // 空指针出现异常 System.out.println(name.length()); } }
-
ArithmeticException
数学运算异样当出现异常的运算条件时,抛出此异样。例如,一个整数“除以零”时,抛出此类的一个实例。
3) ArrayIndexOutOfBoundsException
数组下标越界异样
用非法索引拜访数组时抛出的异样。如果索引为负或大于等于数组大小,则该索引为非法索引。
-
ClassCastException
类型转换异样
当试图将对象强制转换为不是实例的子类时,抛出该异样。例如,以下代码将生成一个ClassCastException
。public class ClassCastException_ {public static void main(String[] args) {A b = new B(); // 向上转型 B b2 = (B)b;// 向下转型,这里是 OK C c2 = (C)b;// 这里抛出 ClassCastException } } class A {} class B extends A {} class C extends A {}
-
NumberFormatException
数字格局不正确异样
当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格局时,抛出该异样 => 应用异样咱们,能够确保输出是满足条件数字.public class NumberFormatException_ {public static void main(String[] args) { String name = "timerring"; // 将 String 转成 int int num = Integer.parseInt(name); // 抛出 NumberFormatException System.out.println(num); } }
编译异样
编译异样是指在编译期间,就必须解决的异样,否则代码不能通过编译。
常见的编译异样
SQLException
:操作数据库时,查问表可能产生异样
IOException
:操作文件时,产生的异样
FileNotFoundException
:当操作一个不存在的文件时,产生异
ClassNotFoundException
:加载类, 而该类不存在时,异样
EOFException
:操作文件, 到文件开端, 产生异样
lllegalArguementException
:参数异样
异样解决
根本介绍
异样解决就是当异样产生时,对异样解决的形式。
异样解决的形式
1) try-catch-finally:程序员在代码中捕捉产生的异样,自行处理
2) throws:将产生的异样抛出,交给调用者 (办法) 来解决, 最顶级的解决者就是 JVM。
示意图
如果程序员没有显示地解决异样,则默认是 throws。
try-catch 异样解决
try-catch 形式解决异样阐明
- Java 提供 try 和 catch 块来解决异样。try 块用于蕴含可能出错的代码。catch 块用于解决 try 块中产生的异样。能够依据须要在程序中有多个 try…catch 块。
-
根本语法
try { // 可疑代码 // 将异样生成对应的异样对象, 传递给 catch 块 }catch(异样){// 对异样的解决} // 如果没有 finally,语法是能够通过
try-catch 形式解决异样细节
- 如果异样产生了,则异样产生前面的代码不会执行,间接进入到 catch 块。
- 如果异样没有产生,则程序执行 try 的代码块,不会进入到 catch。
- 如果心愿不论是否产生异样,都执行某段代码 (比方敞开连贯, 开释资源等)
则应用如下代码 finally {} -
能够有多个 catch 语句,捕捉不同的异样 (进行不同的业务解决),要求父类异
常在后,子类异样在前,比方 (Exception
在后,NullPointerException
在前),如果产生异样,只会匹配一个 catch。(因为如果在后面都让Exception
捕捉了,前面写子类捕捉就没有用了)。package com.hspedu.try_; public class TryCatchDetail02 {public static void main(String[] args) { //1. 如果 try 代码块有可能有多个异样 //2. 能够应用多个 catch 别离捕捉不同的异样,相应解决 //3. 要求子类异样写在后面,父类异样写在前面 try {Person person = new Person(); //person = null; System.out.println(person.getName());//NullPointerException int n1 = 10; int n2 = 0; int res = n1 / n2;//ArithmeticException } catch (NullPointerException e) {System.out.println("空指针异样 =" + e.getMessage()); } catch (ArithmeticException e) {System.out.println("算术异样 =" + e.getMessage()); } catch (Exception e) {System.out.println(e.getMessage()); } finally {}} } class Person { private String name = "jack"; public String getName() {return name;} }
-
能够进行
try-finally
配合应用, 这种用法相当于没有捕捉异样,因而程序会
间接崩掉 / 退出。利用场景就是执行一段代码,不论是否产生异样,都必须执行某个业务逻辑。public class TryCatchDetail03 {public static void main(String[] args) { /* 能够进行 try-finally 配合应用, 这种用法相当于没有捕捉异样,因而程序会间接崩掉 / 退出。利用场景,就是执行一段代码,不论是否产生异 常,都必须执行某个业务逻辑 */ try{ int n1 = 10; int n2 = 0; System.out.println(n1 / n2); }finally {System.out.println("执行了 finally.."); // 执行完间接退出 } System.out.println("程序继续执行.."); // 不会执行 } }
练习
package com.hspedu.try_;
public class TryCatchExercise01 {
}
class Exception01 {public static int method() {
try {String[] names = new String[3];//String[]数组
if (names[1].equals("tom")) {//NullPointerException
System.out.println(names[1]);
} else {names[3] = "hspedu";
}
return 1;
} catch (ArrayIndexOutOfBoundsException e) {return 2;} catch (NullPointerException e) {// 捕捉
return 3; // 然而不从这里返回
} finally { // 必须执行,相当于没有异样捕捉
return 4; // 返回 4
}
}
public static void main(String[] args) {System.out.println(method()); // 输入 4
}
}
package com.hspedu.try_;
public class TryCatchExercise03 {
}
class ExceptionExe01 {public static int method() {
int i = 1;//i = 1
try {
i++;// i=2
String[] names = new String[3];
if (names[1].equals("tom")) { // 空指针
System.out.println(names[1]);
} else {names[3] = "hspedu";
}
return 1;
} catch (ArrayIndexOutOfBoundsException e) {return 2;} catch (NullPointerException e) {return ++i; // i = 3 => 保留长期变量 temp = 3;} finally {
++i; //i = 4
System.out.println("i=" + i);// i = 4
}
}
public static void main(String[] args) {System.out.println(method());// 3
}
}
// 最终输入 i = 4 3
try-catch-finally 执行程序小结
1) 如果没有出现异常,则执行 try 块中所有语句,不执行 catch 块中语句,如果有 finally,最初还须要执行 finally 外面的语句。
2) 如果出现异常,则 try 块中异样产生后,try 块剩下的语句不再执行。将执行 catch 块中的语句,如果有 finally,最初还须要执行 finally 外面的语句。
课后练习题
如果用户输出的不是一个整数,就提醒他重复输出,直到输出一个整数为止
package com.hspedu.try_;
import java.util.Scanner;
public class TryCatchExercise04 {public static void main(String[] args) {
// 如果用户输出的不是一个整数,就提醒他重复输出,直到输出一个整数为止
// 思路
//1. 创立 Scanner 对象
//2. 应用有限循环,去接管一个输出
//3. 而后将该输出的值,转成一个 int
//4. 如果在转换时,抛出异样,阐明输出的内容不是一个能够转成 int 的内容
//5. 如果没有抛出异样,则 break 该循环
Scanner scanner = new Scanner(System.in);
int num = 0;
String inputStr = "";
while (true) {System.out.println("请输出一个整数:"); //
inputStr = scanner.next();
try {num = Integer.parseInt(inputStr); // 这里是可能抛出异样
break;
} catch (NumberFormatException e) {System.out.println("你输出的不是一个整数:");
}
}
System.out.println("你输出的值是 =" + num);
}
}
throws 异样解决
根本介绍
1) 如果一个办法 (中的语句执行时) 可能生成某种异样,然而并不能确定如何解决这种异样,则此办法应 显示地申明抛出异样,表明该办法将不对这些异样进行解决,而由该办法的调用者负责解决。
2) 在办法申明中用 throws 语句能够申明抛出异样的列表,throws 前面的异样类型能够是办法中产生的异样类型, 也能够是它的父类。
疾速入门案例
throws 前面的异样类型能够是办法中产生的异样类型(也能够是异样列表,抛出多个异样),也能够是它的父类(例如 Exception)。
package com.hspedu.throws_;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class Throws01 {public static void main(String[] args) { }
public void f2() throws FileNotFoundException,NullPointerException,ArithmeticException {
// 创立了一个文件流对象
//1. 这里的异样是一个 FileNotFoundException 编译异样
//2. 应用后面讲过的 try-catch-finally
//3. 应用 throws , 抛出异样, 让调用 f2 办法的调用者 (办法) 解决
//4. throws 前面的异样类型能够是办法中产生的异样类型,也能够是它的父类(例如 Exception)
//5. throws 关键字后也能够是 异样列表, 即能够抛出多个异样
FileInputStream fis = new FileInputStream("d://aa.txt");
}
}
注意事项和应用细节
- 对于编译异样, 程序中必须解决,比方 try-catch 或者 throws。
- 对于运行时异样,程序中如果没有解决, 默认就是 throws 的形式解决(相当于办法后有一个 throws XXXException,这时逐级向上,最初 main 办法上可能也默认 throws,这时就给 JVM 解决)。
- 子类重写父类的办法时,对抛出异样的规定:子类重写的办法,所抛出的异样类型要么和父类抛出的异样统一,要么为父类抛出的异样的类型的子类型。
-
在 throws 过程中,如果有办法 try-catch,就相当于解决异样,就能够不用 throws。
例如子类有一个编译异样,应用 throws 抛出,那么父类也必须对该异样做出反馈,或是 throws,或者 try catch,否则同样是编译异样。
自定义异样
基本概念
当程序中呈现了某些“谬误”,但该错误信息并没有在 Throwable
子类中形容解决,这个时候能够本人设计异样类, 用于形容该错误信息。
自定义异样的步骤
1) 定义类: 自定义异样类名 (程序员本人写) 继承 Exception 或 RuntimeException
- 如果继承 Exception,属于编译异样
- 如果继承 RuntimeException,属于运行异样(一般来说, 继承 RuntimeException)
自定义异样的利用实例
当咱们接管 Person 对象年龄时,要求范畴在 18-120 之间, 否则抛出一个自定义异样(要求继承 RuntimeException),并给出提示信息。
package com.hspedu.customexception_;
public class CustomException {
// 办法申明处,throws 异样
public static void main(String[] args) /*throws AgeException*/ {
int age = 180;
// 要求范畴在 18 – 120 之间,否则抛出一个自定义异样
if(!(age >= 18 && age <= 120)) {
// 这里咱们能够通过结构器,设置信息
// 在办法体中,这里 throw 对象
throw new AgeException("年龄须要在 18~120 之间");
}
System.out.println("你的年龄范畴正确.");
}
}
// 自定义一个异样
// 1. 个别状况下,咱们自定义异样是继承 RuntimeException
// 2. 即把自定义异样做成 运行时异样,益处是咱们能够应用默认的解决机制,即主动向上 throws 异样,否则 main 中也得加 throws。class AgeException extends RuntimeException {public AgeException(String message) {// 结构器
super(message); // 调用父结构器,能够进入源码逐级查看。}
}
父结构器:
public Throwable(String message) {fillInStackTrace();
detailMessage = message; // 传入 detailmessage
}
throw 和 throws 的区别
练习
编程题
编写应用程序,接管命令行的两个参数(整数),计算两数相除。
计算两个数相除,要求应用办法 cal(int n1, int n2)
对数据格式不正确(NumberFormatException)、短少命令行参数(ArrayIndexOutOfBoundsException)、除 0 进行异样解决(ArithmeticException)。
package com.hspedu.homework;
public class Homework01 {public static void main(String[] args) {
/*
编写应用程序 EcmDef.java,接管命令行的两个参数(整数),计算两数相除。计算两个数相除,要求应用办法 cal(int n1, int n2)
对数据格式不正确(NumberFormatException)、短少命令行参数(ArrayIndexOutOfBoundsException)、除 0 进行异样解决(ArithmeticException)。*/
try {
// 先验证输出的参数的个数是否正确 两个参数
if(args.length != 2) {throw new ArrayIndexOutOfBoundsException("参数个数不对");
}
// 先把接管到的参数,转成整数
int n1 = Integer.parseInt(args[0]);
int n2 = Integer.parseInt(args[1]);
double res = cal(n1, n2);// 该办法可能抛出 ArithmeticException
System.out.println("计算结果是 =" + res);
} catch (ArrayIndexOutOfBoundsException e) {System.out.println(e.getMessage());
} catch (NumberFormatException e) {System.out.println("参数格局不正确,须要输入整数");
} catch (ArithmeticException e) {System.out.println("呈现了除 0 的异样");
}
}
// 编写 cal 办法,就是两个数的商
public static double cal(int n1, int n2) {return n1 / n2;}
}
文章和代码曾经归档至【Github 仓库:https://github.com/timerring/java-tutorial】或者公众号【AIShareLab】回复 java 也可获取。