异常机制
基本概念
java.lang.Throwable类(超类) :
- 错误(Error) : Java虚拟机无法解决的严重错误,通常无法编码解决
- 异常(Exception) : 描述因编程错误或偶然外在因素导致的轻微错误,通常可以编码解决
- java.lang.Exception类(超类)
- RuntimeException - 运行时异常,也叫作非检测性异常
- ArithmeticException类 - 算术异常
- ArrayIndexOutOfBoundsException类 - 数组下标越界异常
- NullPointerException - 空指针异常
- ClassCastException - 类型转换异常
- NumberFormatException - 数字格式异常
- IOException和其它异常 - 其它异常,也叫作检测性异常,所谓检测性异常就是指在编译阶段都能被编译器检测出来的异常。
注意:
当程序执行过程中发生异常但又没有手动处理时,则由Java虚拟机采用默认方式处理异常,而默认处理方式就是:打印异常的名称、异常发生的原因、异常发生的位置以及终止程序。
// 非检测性异常-运行时异常
System.out.println(5/0); //java.lang.ArithmeticException: / by zero
int[] arr = new int[5];
System.out.println(arr[5]); //java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
String str = null;
System.out.println(str.length()); // java.lang.NullPointerException
Exception ex = new Exception();
IOException ie = (IOException)ex; //java.lang.ClassCastException
System.out.println(Integer.parseInt("123a")); //java.lang.NumberFormatException
捕获
FileInputStream fis = null;
try {
fis = new FileInputStream("./a.txt");
} catch (FileNotFoundException e) {
e.printStackTrace(); //java.io.FileNotFoundException: ./a.txt (No such file or directory)
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace(); // 没有处理 java.lang.NullPointerException 程序终止
} catch (NullPointerException e) {
e.printStackTrace(); // 处理 java.lang.NullPointerException 程序可以正常向下执行
} catch (Exception e) {
e.printStackTrace(); // 放到最后
} finally {
//编写无论是否发生异常都要执行的代码;
}
注意事项
-
当需要编写多个catch分支时,切记小类型应该放在大类型的前面;
-
懒人的写法:catch(Exception e) {}
-
finally通常用于进行善后处理,如:关闭已经打开的文件等
*/ // 执行流程 try { a; b; - 可能发生异常的语句 c; }catch(Exception ex) { d; }finally { e; } 当没有发生异常时的执行流程:a b c e; 当发生异常时的执行流程:a b d e;
finally return
// 1. 返回 -2
private static int withFinally() {
int len = 0;
try {
String s = "abc";
s.length();
return len;
} catch (NullPointerException e) {
len = 1;
return len;
} finally {
System.out.println("执行finally语句");
len = -2;
return len;
}
}
// 2 返回 0
private static int withFinally() {
int len = 0;
try {
String s = "abc";
s.length();
return len;
} catch (NullPointerException e) {
len = 1;
return len;
} finally {
System.out.println("执行finally语句");
// finally里给return用的变量值赋值没用
len = -2;
//return len;
}
}
// 3 返回 1
private static int withFinally() {
int len = 0;
try {
String s = null;
s.length();
return len;
} catch (NullPointerException e) {
len = 1;
return len;
} finally {
System.out.println("执行finally语句");
// finally里给return用的变量值赋值没用
len = -2;
//return len;
}
}
// 4 返回 -2
private static int withFinally() {
int len = 0;
try {
String s = null;
s.length();
return len;
} catch (NullPointerException e) {
len = 1;
return len;
} finally {
System.out.println("执行finally语句");
len = -2;
return len;
}
}
抛出
在某些特殊情况下有些异常不能处理或者不便于处理时,就可以将该异常转移给该方法的调用者,这种方法就叫异常的抛出。当方法执行时出现异常,则底层生成一个异常类对象抛出,此时异常代码后续的代码就不再执行。
public static void show() throws IOException {
}
-
方法重写的原则
-
要求方法名相同、参数列表相同以及返回值类型相同,从jdk1.5开始支持返回子类类型;
-
要求方法的访问权限不能变小,可以相同或者变大;
-
要求方法不能抛出更大的异常;
- 子类重写的方法不能抛出更大的异常、不能抛出平级不一样的异常,但可以抛出一样的异常、更小的异常以及不抛出异常。
经验
-
若父类中被重写的方法没有抛出异常时,则子类中重写的方法只能进行异常的捕获处理。
-
若一个方法内部又以递进方式分别调用了好几个其它方法,则建议这些方法内可以使用抛出的方法处理到最后一层进行捕获方式处理。
-
自定义异常
当需要在程序中表达年龄不合理的情况时,而Java官方又没有提供这种针对性的异常,此时就需要程序员自定义异常加以描述。
// 定义
public class AgeException extends Exception {
static final long serialVersionUID = 7818375828146090155L; // 序列化的版本号 与序列化操作有关系
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}
// 使用
public void setAge(int age) throws AgeException {
if (age > 0 && age < 150) {
this.age = age;
} else {
throw new AgeException("年龄不合理哦!!!");
}
}
public void setAge(int age) {
if (age > 0 && age < 150) {
this.age = age;
} else {
try {
throw new AgeException("年龄不合理哦!!!");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
//Java采用的异常处理机制是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、优雅,并易于维护。
File类
java.io.File类主要用于描述文件或目录路径的抽象表示信息,可以获取文件或目录的特征信息,如:大小等。
- 常用方法
**方法声明 ** | 功能概述 |
---|---|
File(String pathname) | 根据参数指定的路径名来构造对象 |
File(String parent, String child) | 根据参数指定的父路径和子路径信息构造对象 |
File(File parent, String child) | 根据参数指定的父抽象路径和子路径信息构造对象 |
boolean exists() | 测试此抽象路径名表示的文件或目录是否存在 |
String getName() | 用于获取文件的名称 |
long length() | 返回由此抽象路径名表示的文件的长度 |
long lastModifified() | 用于获取文件的最后一次修改时间 |
String getAbsolutePath() | 用于获取绝对路径信息 |
boolean delete() | 用于删除文件,当删除目录时要求是空目录 |
// 文件类
public static void main(String[] args) throws IOException {
// 1. File(String pathname) 根据参数指定的路径名来构造对象
File f1 = new File("./a.txt");
// boolean exists() 文件是否存在
if (f1.exists()) {
// String getName() 用于获取文件的名称
System.out.println("名称:"+f1.getName());
// long length() 返回由此抽象路径名表示的文件的长度
System.out.println("大小:"+f1.length());
// long lastModified() 用于获取文件的最后一次修改时间
Date d1 = new Date(f1.lastModified());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("最后一次修改:"+sdf.format(d1));
// String getAbsolutePath() 用于获取绝对路径信息
System.out.println("绝对路径:"+f1.getAbsolutePath());
// boolean delete() 用于删除文件,当删除目录时要求是空目录
System.out.println("删除:"+f1.delete());
}else {
// boolean createNewFile() 用于创建新的空文件
System.out.println(f1.createNewFile()?"文件创建成功":"文件创建失败");
}
}
// 目录类
// 1
File f = new File("./test");
if (f.exists()) {
System.out.println("目录:"+f.getName());
System.out.println("删除:"+f.delete());
}else {
// boolean mkdir() 用于创建目录 单个目录
System.out.println(f.mkdir()?"目录创建成功":"目录创建失败");
}
// 2
File f = new File("./test/test1/test2/test3");
if (f.exists()) {
System.out.println("目录:"+f.getName());
// 多级目录只删除最内层
System.out.