Java —— 异常及处理
- 1. 异常
- 2. 异常体系
- 3. 常见Exception
- 4. 异常处理
- 4.1 try finally catch关键字
- 4.2 throws和throw 自定义异常
- 4.3 finally,final,finalize三者的区别
1. 异常
异常:在程序执行过程中发生的意外状况,可能导致程序中断或产生错误结果 异常对象:java(面向对象)将错误用类来描述,一旦程序执行错误,将会创建对应的错误对象(用以向程序员或用户展示错误原因等) 异常处理的意义:提高代码的健壮性和可靠性,使程序可以处理非预期的情景,并且继续正常的处理 |
2. 异常体系
异常超类:Thorwable类(表示可抛出)是所有异常和错误的超类 异常的两个子类:Exception异常类,Error错误异常类 Exception程序捕捉处理的异常:表示由于网络故障、文件损坏、设备错误、用户输入非法等情况导致的异常 Error系统错误:表示Java运行时环境出现的错误(JVM内存资源耗尽) |
- java异常体系图
Throwable的父类也是Object,继承其父类的 getClass()和getName()方法
- 常用方法
// 返回抛出异常的详细信息
public string getMessage();
public string getLocalizedMessage();
//返回异常发生时的简要描述
public public String toString()
//打印异常信息到标准输出流上
public void printStackTrace();
public void printStackTrace(PrintStream s);
public void printStackTrace(PrintWriter s)
//记录栈帧的的当前状态
public synchronized Throwable fillInStackTrace();
package exception;
/**
* 常见使用方法
*/
public class ExceptionAPI {
public static void main(String[] args) {
System.out.println("程序开始!");
try {
String line = "1i0";
System.out.println(Integer.parseInt(line));
} catch (NumberFormatException e) {
// 显示红色报错信息
e.printStackTrace();
// 获取错误信息
System.out.println("错误信息:" + e.getMessage());
System.out.println("错误信息Localized:" + e.getLocalizedMessage());
System.out.println("简要描述:" + e.toString());
System.out.println("当前状态:" + e.fillInStackTrace());
}
System.out.println("结束");
}
}
3. 常见Exception
Exception的两类异常:RuntimeException运行时异常(非受控),CheckedException编译时异常(受控) |
常见UncheckedException异常
异常 | 异常描述 |
---|---|
ArrayIndexOutOfBoundsException | 数组越界异常 |
NulPointerException | 空指针异常 |
llegalArgumentException | 非法参数异常 |
NegativeArraySizeException | 数组长度为负异常 |
llegalStateException | 非法状态异常 |
ClassCastException | 类型转换异常 |
常见RuntimeException异常
异常 | 异常描述 |
---|---|
NoSuchFieldException | 表示该类没有指定名称抛出来的异常 |
NoSuchMethodException | 表示该类没有指定方法抛出来的异常 |
llegalAccessException | 不允许访问某个类的异常 |
ClassNotFoundException | 类没有找到抛出异常 |
4. 异常处理
4.1 try finally catch关键字
组合:
try...catch
对某一段代码可能抛出异常进行的捕获
try...finally
对一段代码不管执行情况如何,都会走finally中的代码
try...catch...finally
对异常捕获后,再走fimally中的代码逻辑
- 异常处理过程:一般是子类型在前,超类型在后
对指定代码内容添加一定包围功能(try…finally)快捷键:ctrl+alt+t
try…catch
package exception;
/**
* java异常处理机制
* java异常超类:Throwable
* 两个子类:Error,表示系统级别错误
*/
public class TryCatch {
public static void main(String[] args) {
System.out.println("程序开始执行!");
// try catch异常处理
try{
String line = "";
// String line = null;
System.out.println(line.length());
System.out.println(line.charAt(0));
} catch (NullPointerException e){
// 程序没有异常就不会执行该异常处理
System.out.println("异常:空指针异常!");
} catch (StringIndexOutOfBoundsException e){
// try中的代码执行捕获到第一个异常之后,直接跳到相应的处理机制,后面的异常将不再执行
System.out.println("异常:索引超出范围!");
} catch (NoSuchFieldError | StackOverflowError e){
// 多个异常的相同处理机制
System.out.println("发生异常!");
} catch (Exception e){
// 超类异常(多种异常,超类异常一般写在最后)
System.out.println("出错!");
}
System.out.println("执行完毕!");
}
}
try…catch…finally
package exception;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* finally 关键字用来创建在 try 代码块后面执行的代码块
* 无论是否发生异常,finally 代码块中的代码总会被执行
* 在 finally 代码块中,可以运行清理类型等收尾善后性质的语句
*
* @author LongYongchuan
*/
public class FinallyDemo {
public static void main(String[] args) {
System.out.println("程序开始!");
try{
String line = "11";
System.out.println(line.length());
} catch (Exception e) {
System.out.println("出错了!");
} finally {
System.out.println("finally");
}
System.out.println("程序结束!");
FileOutputStream fos = null;
try {
fos = new FileOutputStream("./document/fos.txt");
fos.write(5);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fos.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
编译器的自动关闭特性(只是编译器认可)
- 只有实现了AutoCloseable接口的类才能在try后面加(进行初始化),java中所有流都实现了该接口
package exception;
import java.io.FileOutputStream;
import java.io.IOException;
public class AutoClose {
public static void main(String[] args) {
// 编译器优化代码(只有实现了AutoCloseable接口的类)
try (
// 初始化
FileOutputStream fos = new FileOutputStream("./document/fos.dat")
) {
fos.write(1);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.2 throws和throw 自定义异常
Java中,异常就是一个对象,它能够被程序员自定义抛出或者应用程序抛出,必须借助于throws和throw 语句来定义抛出异常
throws和throw通常是成对出现的:
throws 语句用在方法声明后面,表示再抛出异常,由该方法的调用者来处理,抛出一个异常实例
throw语句用在方法体内,表示抛出异常,由方法体内的语句处理
- 自定义异常
- Java异常机制可以保证程序更安全和更健壮,虽然Java类库已经提供很多可以直接处理异常的类,但是有时候为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常
- 自定义异常
1.类名要做到见名知义
2.必须继承自Exception(直接或间接继承)
3.提供从超类异常定义的所有构造器
1. throw和throws通常成对出现(单独的throw对Exception时编译不通过,需要使用throws在方法上对异常抛出处理)
2. 一般RuntimeException和throw使用,其他异常需结合throw和throws使用,一般不要在main方法上抛出异常(不负责的体现)
3. 方法中出现throw异常时,throw后面的代码将不执行,而直接进入异常处理机制
- 自定义异常
package exception;
public class IllegalAgeException extends Exception{
// alt+insert键生成
public IllegalAgeException() {
}
public IllegalAgeException(String message) {
super(message);
}
public IllegalAgeException(String message, Throwable cause) {
super(message, cause);
}
public IllegalAgeException(Throwable cause) {
super(cause);
}
public IllegalAgeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
- 抛出异常
package exception;
public class Person{
private String name;
private int age;
private char gender;
private String[] otherInfo;
public Person() {
}
public Person(String name, int age, char gender, String[] otherInfo) {
this.name = name;
this.age = age;
this.gender = gender;
this.otherInfo = otherInfo;
}
public String getName() {
return name;
}
// 异常处理throws关键字(使用在方法声明之后,抛出异常处理,该异常由方法调用者处理)
public void setName(String name){
if (name.length() <= 0 || name.length() >= 5){
// throw和throws通常成对出现(单独的throw对Exception时编译不通过,需要使用throws在方法上对异常抛出处理)
throw new RuntimeException("名字长度不符合汉文名字");
}
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) throws IllegalAgeException{
// 抛出异常throw关键字
if (age < 0 || age >100){
// 一般RuntimeException和throw使用,其他异常需结合throw和throws使用
throw new IllegalAgeException("年龄不合法");
// 出现异常时,throw相当于return直接结束,不执行this.age = age;
}
this.age = age;
System.out.println("年龄:" + age);
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public String[] getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(String[] otherInfo) {
this.otherInfo = otherInfo;
}
}
- 异常处理
package exception;
/**
* throw关键字
*/
public class ThrowDemo {
// 一般不要在main方法上抛出异常
public static void main(String[] args){
Person person = new Person();
// throw单独的异常一般不必须抛出
person.setName("萨克");
// 使用throw和throws抛出的异常必须处理
try {
// 方法调用者处理异常
person.setAge(50);
} catch (IllegalAgeException e) {
throw new RuntimeException(e);
}
System.out.println("此人姓名:" + person.getName());
}
}
注:
允许子类方法抛出父类方法的部分异常
允许子类方法不再抛出异常
允许子类方法抛出父类方法声明的子类型异常
不允许子类方法抛出额外异常
不允许子类方法抛出父类方法声明异常的超类型异常
4.3 finally,final,finalize三者的区别
finally
关键字用于定义在 try-catch 语句块中始终执行的代码块final
关键字用于修饰类、方法和变量,分别表示最终类、最终方法和常量finalize()
方法是 Object 类中的方法,用于对象在被垃圾回收前进行资源清理的操作
finally
:finally
是 Java 中的一个关键字,用于定义在 try-catch 语句块中的一个代码块。无论是否发生异常,finally
代码块始终会被执行(常用于进行清理工作,例如关闭文件、释放资源等)
try {
// 可能引发异常的代码
} catch (Exception e) {
// 异常处理逻辑
} finally {
// 始终会执行的代码,用于清理工作
}
final
:final
是用来修饰类、方法和变量的关键字
- 当用
final
修饰一个类时,表示该类不能被继承,即该类为最终类- 当用
final
修饰一个方法时,表示该方法不能被子类重写,即该方法为最终方法- 当用
final
修饰一个变量时,表示该变量的值不能被修改,即该变量为常量
final class FinalClass {
// 最终类,不能被继承
}
class SuperClass {
final void finalMethod() {
// 最终方法,不能被重写
}
}
public class Example extends SuperClass {
// 尝试重写finalMethod()会导致编译错误
}
class MyClass {
final int MAX_VALUE = 10; // 常量,不能被修改
}
finalize()
:finalize()
是 Object 类中的一个方法,用于在对象被垃圾回收前进行资源清理的操作。当垃圾回收器准备回收一个对象时,会先调用其finalize()
方法(如果该对象重写了该方法),然后才对其进行垃圾回收。通常用于释放非Java堆内存资源,如关闭文件、释放连接等。但是,它已经过时,不推荐使用。
class MyClass {
@Override
protected void finalize() throws Throwable {
// 对象的资源清理操作
}
}