Java异常
文章目录
1 Java中异常体系结构
在Java中,Throwable
类是所有可抛出异常的基类。它的设计初衷是为了支持异常处理机制
JVM默认处理异常的方式
如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
- 把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
- 程序停止执行
示例:常见异常 ’数组越界‘ 做解析 重要
2 Throwable成员方法
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
3 两种处理异常的方式
3.1 try…catch…
try {
// 可能引发异常的代码块
} catch (ExceptionType1 e1) {
// 处理 ExceptionType1 类型的异常
} catch (ExceptionType2 e2) {
// 处理 ExceptionType2 类型的异常
} finally {
// 可选的 finally 块,无论是否发生异常都会执行
}
- 适用于希望在异常发生时立即处理异常的情况
- 允许对不同类型的异常采取不同的处理策略
- 适用于局部异常处理,只在特定的代码块内起作用
- 附带一个finally最终一定会被执行(无论是否抛出异常)
3.2 throws
public void 方法() throws 异常类名 {
}
注意:
- 如果采用 throws 这种方案,将来谁调用谁处理
- 适用于不想在当前方法内处理异常,而是将异常传递给调用者进行处理的情况
- 适用于声明可能抛出多个异常的方法
4 异常的分类 重要
编译和运行的区别
编译是将高级编程语言(如Java、C++)写的源代码转换为目标代码(通常是机器代码或字节码)的过程;
运行是将目标代码加载到计算机内存中,并执行它,实际运行程序以产生期望的结果。
运行发生在编译之后。
编译时异常必须要进行处理,两种处理方案:try…catch …或者 throws
运行时异常可以不处理,出现问题后,需要我们回来修改代码
-
编译时异常checked异常(如目标文件目录不存在异常)
- 都是Exception类及其子类
- 必须显示处理,否则程序就会发生错误,无法通过编译
-
运行时异常runtime异常(数学除0异常)
- 都是RuntimeException类及其子类
- 无需显示处理,也可以和编译时异常一样处理
5 自定义异常
5.1 自定义异常类的编写
自定义一个编译器异常,继承于java.lang.Exception
自定义一个运行时期异常,继承于java.lang.RuntimeException
5.2 自定义异常类的应用
-
自定义一个异常类
public class ScoreException extends Exception { public ScoreException() {} public ScoreException(String message) { super(message); } }
-
在可能出现这个异常的方法中判断是否抛出这个异常
public class ScoreException extends Exception { public ScoreException() {} public ScoreException(String message) { super(message); } }
-
编写示例:
public class Demo { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入分数:"); int score = sc.nextInt(); Teacher t = new Teacher(); try { t.checkScore(score); } catch (ScoreException e) { e.printStackTrace(); } } }
6. IO异常的处理
6.1 JDK7前处理
之前的入门练习,我们一直把异常抛出,而实际开发中并不能这样处理,建议使用try...catch...finally
代码块,处理异常部分,代码使用演示:
public class HandleException1 {
public static void main(String[] args) {
// 声明变量
FileWriter fw = null;
try {
//创建流对象
fw = new FileWriter("fw.txt");
// 写出数据
fw.write("黑马程序员"); //黑马程序员
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6.2 JDK7的处理(扩展知识点了解内容)
还可以使用JDK7优化后的try-with-resource
语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。
格式:
try (创建流对象语句,如果多个,使用';'隔开) {
// 读写数据
} catch (IOException e) {
e.printStackTrace();
}
代码使用演示:
public class HandleException2 {
public static void main(String[] args) {
// 创建流对象
try ( FileWriter fw = new FileWriter("fw.txt"); ) {
// 写出数据
fw.write("黑马程序员"); //黑马程序员
} catch (IOException e) {
e.printStackTrace();
}
}
}
6.3 JDK9的改进(扩展知识点了解内容)
JDK9中try-with-resource
的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close,我们来了解一下格式。
改进前格式:
// 被final修饰的对象
final Resource resource1 = new Resource("resource1");
// 普通对象
Resource resource2 = new Resource("resource2");
// 引入方式:创建新的变量保存
try (Resource r1 = resource1;
Resource r2 = resource2) {
// 使用对象
}
改进后格式:
// 被final修饰的对象
final Resource resource1 = new Resource("resource1");
// 普通对象
Resource resource2 = new Resource("resource2");
// 引入方式:直接引入
try (resource1; resource2) {
// 使用对象
}
改进后,代码使用演示:
public class TryDemo {
public static void main(String[] args) throws IOException {
// 创建流对象
final FileReader fr = new FileReader("in.txt");
FileWriter fw = new FileWriter("out.txt");
// 引入到try中
try (fr; fw) {
// 定义变量
int b;
// 读取数据
while ((b = fr.read())!=-1) {
// 写出数据
fw.write(b);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}