Day37--error和exception
Day37--error和exception
Exception 异常
Error 错误
目录:
1、什么是异常
2、异常体系结构
3、Java异常处理机制
4、处理异常
5、自定义异常
6、总结
什么是异常
实际工作中,遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求,你的程序要打开某个文件,这个文件可能不存在或者文件格式不对,你要读取数据库的数据,数据可能是空的等。我们的程序再跑着,内存或硬盘可能满了。等等。
软件程序在运行过程中,非常可能遇到刚刚提到的这些异常问题,我们叫异常,英文是:Exception,意思是例外。这些,例外情况,或者叫异常,怎么让我们写的程序做出合理的处理。而不至于程序崩溃。
异常指程序运行中出现的不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。
异常发生在程序运行期间,它影响了正常的程序执行流程。
有的异常,在IDEA未运行的时候,就提示出来了,及时改正就可以了。但是,有的错,只有当代码运行起来,才能知道
示例1:
在Demo01里面,创建main方法,再创建main方法之外的a、b方法。a方法的内容是调用b方法;b方法的内容是调用a方法。然后在main方法里面实例化Demo01,调用a方法,然后执行
package com.liu.exception;
public class Demo01 {
public static void main(String[] args) {
new Demo01().a();
}
public void a() {
b();
}
public void b() {
a();
}
}
/*
Exception in thread "main" java.lang.StackOverflowError 程序因为栈溢出而异常终止。
at com.liu.exception.Demo01.b(Demo01.java:13)
at com.liu.exception.Demo01.a(Demo01.java:9)
at com.liu.exception.Demo01.b(Demo01.java:13)
at com.liu.exception.Demo01.a(Demo01.java:9)
at com.liu.exception.Demo01.b(Demo01.java:13)
at com.liu.exception.Demo01.a(Demo01.java:9)
at com.liu.exception.Demo01.b(Demo01.java:13)
*/
异常形式 java.lang.StackOverflowError 程序因为栈溢出而异常终止。
代码易错:
package com.liu.exception;
public class Demo01 {
public static void main(String[] args) {
a(); //出错
}
public void a() {
b();
}
public void b() {
a();
}
}
详细解释:
-
问题分析
- 在Java中,
main
方法是一个静态方法。静态方法属于类本身,而不是类的实例。它可以在没有创建类的对象的情况下被调用。 - 然而,在这个
Demo01
类中,a
方法是非静态的(没有static
关键字修饰)。非静态方法属于类的实例,需要通过类的对象来调用。 - 当在
main
方法(静态方法)中直接调用a
方法(非静态方法)时,就会出现“无法从静态上下文中引用非静态方法”的错误。这是因为静态方法中没有隐含的this
对象(this
指向当前实例)来调用非静态方法。
- 在Java中,
-
解决方法
- 有两种常见的解决方法:
- 方法一:将
a
方法改为静态方法- 如果
a
方法不需要访问类的实例变量,可以将a
方法改为静态方法。修改后的代码如下:
- 如果
- 方法一:将
- 有两种常见的解决方法:
package com.liu.exception;
public class Demo01 {
public static void main(String[] args) {
a();
}
public static void a() {
b();
}
public static void b() {
a();
}
}
- 这样,因为`a`方法变成了静态方法,就可以在`main`方法中直接调用了。
- **方法二:通过类的实例来调用`a`方法**
- 创建`Demo01`类的一个实例,然后通过这个实例来调用`a`方法。修改后的代码如下:
package com.liu.exception;
public class Demo01 {
public static void main(String[] args) {
new Demo01().a();
}
public void a() {
b();
}
public void b() {
a();
}
}
- 这里通过`new Demo01()`创建了`Demo01`类的一个对象,然后使用这个对象来调用`a`方法,这样就符合了非静态方法需要通过实例来调用的规则。
再例如:
整数相除;除数是0
package com.liu.exception;
public class Demo01 {
public static void main(String[] args) {
System.out.println(11/0);//ArithmeticException
}
}
ArithmeticException:计算异常 (Arithmetic:计算)
这种异常通常会在以下情况下被抛出:
-
整数除零:当尝试用0作为除数进行整数除法操作时(例如,
int result = 10 / 0;
),会抛出ArithmeticException
。 -
取余运算中的零除数:与整数除零类似,当在取余运算(模运算)中使用0作为除数时(例如,
int remainder = 10 % 0;
),也会抛出此异常。需要注意的是,浮点除法(例如,
double result = 10.0 / 0.0;
)不会产生ArithmeticException
,而是会得到Infinity
或NaN
(非数字)作为结果,这是因为在Java中,浮点数的除零操作有明确的数学定义。
要理解Java异常处理机制,你需要掌握以下三种类型的异常和错误:
检查性异常(Checked Exception):
检查性异常是在编译时被检查并要求处理的异常。这些异常通常是由用户错误或外部问题引起的,程序员在编写代码时需要预见并处理这些异常。例如,当尝试打开一个不存在的文件时,会抛出一个FileNotFoundException,这是一个检查性异常。编译器会强制程序员在代码中处理这些异常,要么通过捕获异常(使用try-catch语句),要么通过声明异常(在方法签名中使用throws关键字)。
运行时异常(Unchecked Exception):
运行时异常是在运行时发生的异常,这些异常通常是编程错误或不可预见的问题引起的。与检查性异常不同,运行时异常在编译时不会被检查,因此程序员可以选择是否处理这些异常。常见的运行时异常包括NullPointerException(空指针异常)、ArithmeticException(算术异常)等。虽然编译器不会强制处理这些异常,但良好的编程实践是尽可能捕获和处理这些潜在的异常,以提高程序的健壮性和稳定性。
错误(Error):
错误是Java中比异常更严重的问题,它们通常表示JVM(Java虚拟机)层面的严重问题,如内存不足、栈溢出等。错误在代码中通常无法被捕获或处理,因为它们是系统级的错误,超出了程序员的控制范围。当发生错误时,JVM通常会选择终止线程或进程。虽然程序员无法直接处理错误,但了解错误的类型和原因有助于编写更健壮的代码,并减少错误发生的可能性。
异常体系结构
Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
在JavaAPl中已经定义了许多异常类,这些异常类分为两大类,错误Error和异常Exception。
Error
- Error类对象由Java虚拟机生成并抛出,大多数错误与代码编写者所执行的操作无关。
- Java虚拟机运行错误(Virtual MachineError),当JVM不再有继续执行操作所需的内存资源时,将出现OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止;
- 还有发生在虚拟机试图执行应用时,如类定义错误(NoClassDefFoundError)、链接错误(LinkageError)。这些错误是不可查的,因为它们在应用程序的控制和处理能力之外,而且绝大多数是程序运行时不允许出现的状况。
Exception
- 在Exception分支中有一个重要的子类RuntimeException(运行时异常)
- ArrayIndexOutOfBoundsException(数组下标越界)
- NullPointerException(空指针异常)
- ArithmeticException(算术异常)
- MissingResourceException(丢失资源)
- ClassNotFoundException(找不到类)等异常,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。
- 这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生;
- Error和Exception的区别:Error通常是灾难性的致命的错误,是程序无法控制和处理的,当出现这些异常时,Java虚拟机(JVM)一般会选择终止线程;Exception通常情况下是可以被程序处理的,并且在程序中应该尽可能的去处理这些异常。