- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章全面了解java中的异常处理由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Java 的异常处理是 Java 语言的一大重要特性,也是提高代码健壮性的最强大方法之一。当我们编写了错误的代码时,编译器在编译期间可能会抛出异常,有时候即使编译正常,在运行代码的时候也可能会抛出异常.
什么是异常 。
Java 中异常类的架构 。
如何进行异常处理 。
如何自定义异常 。
什么是异常链 。
如何使用异常链 。
1.8/25 。
2.编程不能停,成为运维开发性人才 。
3.计算机408基础打好,编程语言学精通,然后走下去 。
4.Docker和K8s继续 。
异常就是程序上的错误,我们在编写程序的时候经常会产生错误,这些错误划分为编译期间的错误和运行期间的错误.
下面我们来看几个常见的异常案例.
如果语句漏写分号,程序在编译期间就会抛出异常,实例如下:
1
2
3
4
5
|
public
class
Hello {
public
static
void
main(String[] args) {
System.out.println(
"Hello World!"
)
}
}
|
运行结果:
1
2
3
4
5
|
$ javac Hello.java
Hello.java:
3
: 错误: 需要
';'
System.out.println(
"Hello World!"
)
^
1
个错误
|
static 关键字写成了 statci,实例如下:
1
2
3
4
|
Hello.java:
2
: 错误: 需要<标识符>
public
statci
void
main(String[] args) {
^
1
个错误
|
当数组下标越界,程序在编译阶段不会发生错误,但在运行时会抛出异常。实例如下:
1
2
3
4
5
6
|
public
class
ArrayOutOfIndex {
public
static
void
main(String[] args) {
int
[] arr = {
1
,
2
,
3
};
System.out.println(arr[
3
]);
}
}
|
运行结果:
1
2
|
Exception in thread
"main"
java.lang.ArrayIndexOutOfBoundsException: Index
3
out of bounds
for
length
3
at ArrayOutOfIndex.main(ArrayOutOfIndex.java:
4
)
|
在 Java 中,通过 Throwable 及其子类来描述各种不同类型的异常。如下是 Java 异常类的架构图(不是全部,只展示部分类):
Throwable 位于 java.lang 包下,它是 Java 语言中所有错误(Error)和异常(Exception)的父类.
Throwable 包含了其线程创建时线程执行堆栈的快照,它提供了 printStackTrace() 等接口用于获取堆栈跟踪数据等信息.
主要方法:
fillInStackTrace
: 用当前的调用栈层次填充 Throwable
对象栈层次,添加到栈层次任何先前信息中;getMessage
:返回关于发生的异常的详细信息。这个消息在 Throwable
类的构造函数中初始化了;getCause
:返回一个 Throwable
对象代表异常原因;getStackTrace
:返回一个包含堆栈层次的数组。下标为 0 的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底;printStackTrace
:打印 toString()
结果和栈层次到 System.err
,即错误输出流。
Error 是 Throwable 的一个直接子类,它可以指示合理的应用程序不应该尝试捕获的严重问题。这些错误在应用程序的控制和处理能力之外,编译器不会检查 Error,对于设计合理的应用程序来说,即使发生了错误,本质上也无法通过异常处理来解决其所引起的异常状况.
常见 Error:
AssertionError
:断言错误;VirtualMachineError
:虚拟机错误;UnsupportedClassVersionError
:Java 类版本错误;OutOfMemoryError
:内存溢出错误。
Exception 是 Throwable 的一个直接子类。它指示合理的应用程序可能希望捕获的条件.
Exception 又包括 Unchecked Exception(非检查异常)和 Checked Exception(检查异常)两大类别.
Unchecked Exception 是编译器不要求强制处理的异常,包含 RuntimeException 以及它的相关子类。我们编写代码时即使不去处理此类异常,程序还是会编译通过.
常见非检查异常:
NullPointerException
:空指针异常;ArithmeticException
:算数异常;ArrayIndexOutOfBoundsException
:数组下标越界异常;ClassCastException
:类型转换异常。Checked Exception 是编译器要求必须处理的异常,除了 RuntimeException 以及它的子类,都是 Checked Exception 异常。我们在程序编写时就必须处理此类异常,否则程序无法编译通过.
常见检查异常:
IOException
:IO 异常SQLException
:SQL 异常
在 Java 语言中,异常处理机制可以分为两部分:
Java 通过 5 个关键字来实现异常处理,分别是:throw、throws、try、catch、finally.
异常总是先抛出,后捕获的。下面我们将围绕着 5 个关键字来详细讲解如何抛出异常以及如何捕获异常.
我们先来看一个除零异常的实例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
package
com.caq.exception;
public
class
Demo01 {
//打印a/b的结果
public
static
void
test(
int
a,
int
b){
System.out.println(a/b);
}
public
static
void
main(String[] args) {
//调用test方法
test(
5
,
0
);
}
}
|
运行结果:
1
2
3
4
5
|
Exception in thread
"main"
java.lang.ArithmeticException: / by zero
at com.caq.exception.Demo01.test(Demo01.java:
6
)
at com.caq.exception.Demo01.main(Demo01.java:
11
)
Process finished with exit code
1
|
我们知道 0 是不能用作除数的,由于 test() 方法中除数 b 为 0,所以代码将停止执行并显示了相关的异常信息,此信息为堆栈跟踪 。
上面的运行结果告诉我们:main 线程发生了类型为 ArithmeticException 的异常,显示消息为 by zero,并且提示了可能发生异常的方法和行号.
上面的实例中,程序在运行时引发了错误,那么如何来显示抛出(创建)异常呢?
我们可以使用 throw 关键字来抛出异常,throw 关键字后面跟异常对象,改写上面的实例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package
com.caq.exception;
public
class
Demo01 {
//打印a/b的结果
public
static
void
test(
int
a,
int
b){
if
(b==
0
){
//抛出异常
throw
new
ArithmeticException(
"被除数不能为零"
);
}
System.out.println(a/b);
}
public
static
void
main(String[] args) {
//调用test方法
test(
5
,
0
);
}
}
|
运行结果:
1
2
3
|
Exception in thread
"main"
java.lang.ArithmeticException: 被除数不能为零
at com.caq.exception.Demo01.test(Demo01.java:
8
)
at com.caq.exception.Demo01.main(Demo01.java:
15
)
|
代码在运行时同样引发了错误,但显示消息为 “除数不能为零”。我们看到 test() 方法中加入了条件判断,如果调用者将参数 b 设置为 0 时,会使用 throw 关键字来抛出异常,throw 后面跟了一个使用 new 关键字实例化的算数异常对象,并且将消息字符串作为参数传递给了算数异常的构造函数.
我们可以使用 throw 关键字抛出任何类型的 Throwable 对象,它会中断方法,throw 语句之后的所有内容都不会执行。除非已经处理抛出的异常。异常对象不是从方法中返回的,而是从方法中抛出的.
可以通过 throws 关键字声明方法要抛出何种类型的异常。如果一个方法可能会出现异常,但是没有能力处理这种异常,可以在方法声明处使用 throws 关键字来声明要抛出的异常。例如,汽车在运行时可能会出现故障,汽车本身没办法处理这个故障,那就让开车的人来处理.
throws 用在方法定义时声明该方法要抛出的异常类型,如下是伪代码:
1
2
3
|
public
void
demoMethod()
throws
Exception1, Exception2, ... ExceptionN {
// 可能产生异常的代码
}
|
throws 后面跟的异常类型列表可以有一个也可以有多个,多个则以 , 分割。当方法产生异常列表中的异常时,将把异常抛向方法的调用方,由调用方处理.
throws 有如下使用规则:
Error
、RuntimeException
以及的子类),那么可以不使用 throws
关键字来声明要抛出的异常,编译器能够通过编译,但在运行时会被系统抛出;throws
声明将其抛出或使用 try catch
捕获异常,否则将导致编译错误;
使用 try 和 catch 关键字可以捕获异常。try catch 代码块放在异常可能发生的地方。它的语法如下:
Tips: 再IDEA里可以通过//ctrl+alt+t选择代码自动包裹 。
1
2
3
4
5
6
7
8
9
|
try
{
// 可能会发生异常的代码块
}
catch
(Exception e1) {
// 捕获并处理try抛出的异常类型Exception
}
catch
(Exception2 e2) {
// 捕获并处理try抛出的异常类型Exception2
}
finally
{
// 无论是否发生异常,都将执行的代码块
}
|
我们来看一下上面语法中的 3 种语句块:
try
语句块:用于监听异常,当发生异常时,异常就会被抛出;catch
语句块:catch
语句包含要捕获的异常类型的声明,当 try
语句块发生异常时,catch
语句块就会被检查。当 catch
块尝试捕获异常时,是按照 catch
块的声明顺序从上往下寻找的,一旦匹配,就不会再向下执行。因此,如果同一个 try
块下的多个 catch
异常类型有父子关系,应该将子类异常放在前面,父类异常放在后面;finally
语句块:无论是否发生异常,都会执行 finally
语句块。finally
常用于这样的场景:由于 finally
语句块总是会被执行,所以那些在 try
代码块中打开的,并且必须回收的物理资源(如数据库连接、网络连接和文件),一般会放在 finally
语句块中释放资源。try 语句块后可以接零个或多个 catch 语句块,如果没有 catch 块,则必须跟一个 finally 语句块。简单来说,try 不允许单独使用,必须和 catch 或 finally 组合使用,catch 和 finally 也不能单独使用.
实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package
com.caq.exception;
public
class
Demo01 {
//打印a/b的结果
public
static
void
test(
int
a,
int
b){
System.out.println(a/b);
}
public
static
void
main(String[] args) {
//调用test方法
try
{
test(
5
,
0
);
}
catch
(ArithmeticException e1){
System.out.println(
"捕获的异常为:"
+e1);
}
finally
{
System.out.println(
"无论是否发送异常,我都会执行哦~"
);
}
}
}
|
运行结果:
1
2
|
捕获的异常为:java.lang.ArithmeticException: / by zero
无论是否发送异常,我都会执行哦~
|
test() 方法中除数 b 为 0,会发生除零异常,我们在方法调用处使用了 try 语句块对异常进行捕获;如果捕获到了异常, catch 语句块会对 ArithmeticException 类型的异常进行处理,此处打印了一行自定义的提示语句; 。
最后的 finally 语句块,无论发生异常与否,总会执行.
Java 7 以后,catch 多种异常时,也可以像下面这样简化代码:
1
2
3
4
5
6
7
|
try
{
// 可能会发生异常的代码块
}
catch
(Exception | Exception2 e) {
// 捕获并处理try抛出的异常类型
}
finally
{
// 无论是否发生异常,都将执行的代码块
}
|
自定义异常,就是定义一个类,去继承 Throwable 类或者它的子类.
Java 内置了丰富的异常类,通常使用这些内置异常类,就可以描述我们在编码时出现的大部分异常情况。一旦内置异常无法满足我们的业务要求,就可以通过自定义异常描述特定业务产生的异常类型.
实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
class
ExceptionDemo4 {
static
class
MyCustomException
extends
RuntimeException {
/**
* 无参构造方法
*/
public
MyCustomException() {
super
(
"我的自定义异常"
);
}
}
public
static
void
main(String[] args) {
// 直接抛出异常
throw
new
MyCustomException();
}
}
|
运行结果:
1
2
|
Exception in thread
"main"
ExceptionDemo4$MyCustomException: 我的自定义异常
at ExceptionDemo4.main(ExceptionDemo4.java:
13
)
|
在代码中写了一个自定义异常 MyCustomException,继承自 RuntimeException,它是一个静态内部类,这样在主方法中就可以直接抛出这个异常类了。当然,也可以使用 catch 来捕获此类型异常.
异常链是以一个异常对象为参数构造新的异常对象,新的异常对象将包含先前异常的信息。简单来说,就是将异常信息从底层传递给上层,逐层抛出,我们来看一个实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
public
class
ExceptionDemo5 {
/**
* 第一个自定义的静态内部异常类
*/
static
class
FirstCustomException
extends
Exception {
// 无参构造方法
public
FirstCustomException() {
super
(
"第一个异常"
);
}
}
/**
* 第二个自定义的静态内部异常类
*/
static
class
SecondCustomException
extends
Exception {
public
SecondCustomException() {
super
(
"第二个异常"
);
}
}
/**
* 第三个自定义的静态内部异常类
*/
static
class
ThirdCustomException
extends
Exception {
public
ThirdCustomException() {
super
(
"第三个异常"
);
}
}
/**
* 测试异常链静态方法1,直接抛出第一个自定义的静态内部异常类
* @throws FirstCustomException
*/
public
static
void
f1()
throws
FirstCustomException {
throw
new
FirstCustomException();
}
/**
* 测试异常链静态方法2,调用f1()方法,并抛出第二个自定义的静态内部异常类
* @throws SecondCustomException
*/
public
static
void
f2()
throws
SecondCustomException {
try
{
f1();
}
catch
(FirstCustomException e) {
throw
new
SecondCustomException();
}
}
/**
* 测试异常链静态方法3,调用f2()方法, 并抛出第三个自定义的静态内部异常类
* @throws ThirdCustomException
*/
public
static
void
f3()
throws
ThirdCustomException {
try
{
f2();
}
catch
(SecondCustomException e) {
throw
new
ThirdCustomException();
}
}
public
static
void
main(String[] args)
throws
ThirdCustomException {
// 调用静态方法f3()
f3();
}
}
|
运行结果:
1
2
3
|
Exception in thread
"main"
ExceptionDemo5$ThirdCustomException: 第三个异常
at ExceptionDemo5.f3(ExceptionDemo5.java:
46
)
at ExceptionDemo5.main(ExceptionDemo5.java:
51
)
|
通过运行结果,我们只获取到了静态方法 f3() 所抛出的异常堆栈信息,前面代码所抛出的异常并没有被显示.
我们改写上面的代码,让异常信息以链条的方式 “连接” 起来。可以通过改写自定义异常的构造方法,来获取到之前异常的信息。实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
public
class
ExceptionDemo6 {
/**
* 第一个自定义的静态内部异常类
*/
static
class
FirstException
extends
Exception {
// 无参构造方法
public
FirstException() {
super
(
"第一个异常"
);
}
}
/**
* 第二个自定义的静态内部异常类
*/
static
class
SecondCustomException
extends
Exception {
/**
* 通过构造方法获取之前异常的信息
* @param cause 捕获到的异常对象
*/
public
SecondCustomException(Throwable cause) {
super
(
"第二个异常"
, cause);
}
}
/**
* 第三个自定义的静态内部异常类
*/
static
class
ThirdCustomException
extends
Exception {
/**
* 通过构造方法获取之前异常的信息
* @param cause 捕获到的异常对象
*/
public
ThirdCustomException(Throwable cause) {
super
(
"第三个异常"
, cause);
}
}
/**
* 测试异常链静态方法1,直接抛出第一个自定义的静态内部异常类
* @throws FirstException
*/
public
static
void
f1()
throws
FirstException {
throw
new
FirstException();
}
/**
* 测试异常链静态方法2,调用f1()方法,并抛出第二个自定义的静态内部异常类
* @throws SecondCustomException
*/
public
static
void
f2()
throws
SecondCustomException {
try
{
f1();
}
catch
(FirstException e) {
throw
new
SecondCustomException(e);
}
}
/**
* 测试异常链静态方法3,调用f2()方法, 并抛出第三个自定义的静态内部异常类
* @throws ThirdCustomException
*/
public
static
void
f3()
throws
ThirdCustomException {
try
{
f2();
}
catch
(SecondCustomException e) {
throw
new
ThirdCustomException(e);
}
}
public
static
void
main(String[] args)
throws
ThirdCustomException {
// 调用静态方法f3()
f3();
}
}
|
运行结果:
1
2
3
4
5
6
7
8
9
10
11
|
Exception in thread
"main"
ExceptionDemo6$ThirdCustomException: 第三个异常
at ExceptionDemo6.f3(ExceptionDemo6.java:
74
)
at ExceptionDemo6.main(ExceptionDemo6.java:
80
)
Caused by: ExceptionDemo6$SecondCustomException: 第二个异常
at ExceptionDemo6.f2(ExceptionDemo6.java:
62
)
at ExceptionDemo6.f3(ExceptionDemo6.java:
72
)
...
1
more
Caused by: ExceptionDemo6$FirstException: 第一个异常
at ExceptionDemo6.f1(ExceptionDemo6.java:
51
)
at ExceptionDemo6.f2(ExceptionDemo6.java:
60
)
...
2
more
|
通过运行结果,我们看到,异常发生的整个过程都打印到了屏幕上,这就是一个异常链.
通过学习,我们知道了异常就是程序上的错误,良好的异常处理可以提高代码的健壮性.
Java 语言中所有错误(Error)和异常(Exception)的父类都是 Throwable.
Error 和 Exception 是 Throwable 的直接子类,我们通常说的异常处理实际上就是处理 Exception 及其子类,异常又分为检查型异常和非检查型异常.
通过抛出异常和捕获异常来实现异常处理。我们亦可以通过继承 Throwable 类或者它的子类来自定义异常类。通过构造方法获取之前异常的信息可以实现异常链 。
以上就是全面了解java中的异常处理的详细内容,更多关于java异常处理的资料请关注我其它相关文章! 。
原文链接:https://blog.csdn.net/qq_45714272/article/details/119912609 。
最后此篇关于全面了解java中的异常处理的文章就讲到这里了,如果你想了解更多关于全面了解java中的异常处理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!