异常机制(重点)
基本概念
- 异常就是”不正常”的含义,在Java语言中主要指程序执行中发生的不正常情况。
- java.lang.Throwable类是Java语言中错误(Error)和异常(Exception)的超类。
- 其中Error类主要用于描述Java虚拟机无法解决的严重错误,通常无法编码解决,如:JVM挂掉了等。
其中Exception类主要用于描述因编程错误或偶然外在因素导致的轻微错误,通常可以编码解决,如:0作为除数等。
异常的分类
java.lang.Exception类是所有异常的超类,主要分为以下两种:
- RuntimeException - 运行时异常,也叫作非检测性异常
- IOException和其它异常 - 其它异常,也叫作检测性异常,所谓检测性异常就是指在编译阶段都能被编译器检测出来的异常。
- RuntimeException - 运行时异常,也叫作非检测性异常
- 其中RuntimeException类的主要子类:
- ArithmeticException类 - 算术异常
- ArrayIndexOutOfBoundsException类 - 数组下标越界异常
- NullPointerException - 空指针异常
- ClassCastException - 类型转换异常
- NumberFormatException - 数字格式异常
- ArithmeticException类 - 算术异常
- 注意:
- 当程序执行过程中发生异常但又没有手动处理时,则由Java虚拟机采用默认方式处理异常,而默认处理方式就是:打印异常的名称、异常发生的原因、异常发生的位置以及终止程序。
异常的避免
- 在以后的开发中尽量使用if条件判断来避免异常的发生。
- 但是过多的if条件判断会导致程序的代码加长、臃肿,可读性差。
异常的捕获
语法格式:
try {
编写可能发生异常的代码;
}catch(异常类型 引用变量名) {
编写针对该类异常的处理代码;
}…
finally {
编写无论是否发生异常都要执行的代码;
}
注意事项:
- 当需要编写多个catch分支时,切记小类型应该放在大类型的前面;
- 懒人的写法:catch(Exception e) {}
- finally通常用于进行善后处理,如:关闭已经打开的文件等。
执行流程:
try {
a;
b; - 可能发生异常的语句
c;
}catch(Exception ex) {
d;
}finally {
e;
}
当没有发生异常时的执行流程:a b c e;
当发生异常时的执行流程:a b d e;
package com.lagou.task16;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author lijing
* @date 2020/10/13 14:17
* @description
*/
public class ExceptionCatchTest {
public static void main(String[] args) {
FileInputStream fis = null;
try {
System.out.println("1");
fis = new FileInputStream("d:/a.txt");
System.out.println(2);
} catch (FileNotFoundException e) {
System.out.println(3);
e.printStackTrace();
System.out.println(4);
}
try {
System.out.println(5);
fis.close();
System.out.println(6);
} catch (IOException e) {
System.out.println(7);
e.printStackTrace();
System.out.println(8);
}catch(NullPointerException e){
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("世界上最真情的相依就是你在try我在catch,无论你发什么脾气我都默默承受并处理,到那时再来期待我们的finally");
//当程序执行工程中没有发生异常的执行流程是:1 2 4 5 世界..
//当程序执行过程中发生异常又没有手动处理空指针异常时的执行流程 1 3 4 5 空指针异常
//当程序执行过程中发生异常有手动处理空指针异常时的执行流程 1 3 4 5 世界上
}
}
package com.lagou.task16;
/**
* @author lijing
* @date 2020/10/13 14:31
* @description
*/
public class ExceptionFinally {
//笔试考点
public static int test(){
try{
int[] arr=new int[5];
System.out.println(arr[5]);
return 0;
}catch (ArrayIndexOutOfBoundsException e){
e.printStackTrace();
return 1;
}finally {
return 2;
}
}
public static void main(String[] args) {
try {
int ia=10;
// int ib=1;
int ib=0;
System.out.println(ia/ib);
}catch (ArithmeticException e){
e.printStackTrace();
/*String str1=null;
str1.length();*///会发生空指针异常
}finally {
System.out.println("无论是否发生异常都会执行");
}
System.out.println("Over!");
int test = test();
System.out.println(test);
}
}
异常的抛出
- 基本概念:
在某些特殊情况下有些异常不能处理或者不便于处理时,就可以将该异常转移给该方法的调用者,这种方法就叫异常的抛出。当方法执行时出现异常,则底层生成一个异常类对象抛出,此时异常代码后续的代码就不再执行。
- 语法格式:
访问权限 返回值类型 方法名称(形参列表) throws 异常类型1,异常类型2,…{ 方法体; }
如: public void show() throws IOException{}
- 遗留问题:方法重写的原则:
a.要求方法名相同、参数列表相同以及返回值类型相同,从jdk1.5开始支持返回子类类型;
b.要求方法的访问权限不能变小,可以相同或者变大;
c.要求方法不能抛出更大的异常;
- 注意:
子类重写的方法不能抛出更大的异常、不能抛出平级不一样的异常,但可以抛出一样的异常、更小的异常以及不抛出异常。
经验分享
基本概念
当需要在程序中表达年龄不合理的情况时,而Java官方又没有提供这种针对性的异常,此时就需要程序员自定义异常加以描述。
- 实现流程
a.自定义xxxException异常类继承Exception类或者其子类。
b.提供两个版本的构造方法,一个是无参构造方法,另外一个是字符串作为参数的构造方法。
- 异常的产生
throw new 异常类型(实参);
方法声明功能概述
如: throw new AgeException(“年龄不合理!!!”);
- Java采用的异常处理机制是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序简洁、优雅,并易于维护。 ```java package com.lagou.task16;
/**
- @author lijing
- @date 2020/10/13 15:13
@description */ public class AgeException extends Exception{ static final long serialVersionUID = -3387516993124229948L;//序列化的版本号,与序列化操作有关系 public AgeException() { }
public AgeException(String message) {
super(message);
} }
```java
public class Person {
public void setAge(int age) /*throws AgeException*/ {
if (age>0 &&age<150){
this.age = age;
}else{
// System.out.println("年龄不合理");
try {
throw new AgeException("年龄不合理哟");
} catch (AgeException e) {
e.printStackTrace();
}
}
}
}
File类(重点)
java.io.File类主要用于描述文件或目录路径的抽象表示信息,可以获取文件或目录的特征信息,如:大小等。
File(String pathname) |
根据参数指定的路径名来构造对象 |
---|---|
File(String parent, String child) |
根据参数指定的父路径和子路径信息构造对象 |
File(File parent, String child) |
根据参数指定的父抽象路径和子路径信息构造对象 |
boolean exists() |
测试此抽象路径名表示的文件或目录是否存在 |
String getName() |
用于获取文件的名称 |
long length() |
返回由此抽象路径名表示的文件的长度 |
long lastModified() |
用于获取文件的最后一次修改时间 |
String getAbsolutePath() |
用于获取绝对路径信息 |
boolean delete() |
用于删除文件,当删除目录时要求是空目录 |
boolean createNewFile() |
用于创建新的空文件 |
boolean mkdir() 用于创建目录 boolean mkdirs() 用于创建多级目录 File[] listFiles() 获取该目录下的所有内容 boolean isFile() 判断是否为文件 boolean isDirectory() 判断是否为目录 File[] listFiles(FileFilter filter) 获取目录下满足筛选器的所有内容 |
package com.lagou.task16;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
/**
* @author lijing
* @date 2020/10/13 15:25
* @description
*/
public class FileTest {
//自定义成员方法实现指定目录以及子目录中所有内容的打印
public static void show(File file){
File[] files = file.listFiles();
for (File tl :files) {
String name=tl.getName();
//判断是否为文件,若是则则直接打印文件名称
if (tl.isFile() ){
System.out.println(name);
}
if (tl.isDirectory()){
System.out.println("[" + name + "]");
show(tl);
}
}
}
public static void main(String[] args) throws IOException {
//1.构造File类型的对象与D:/a.txt文件关联
File f1=new File("D:/a.txt");
//2.若文件存在则获取文件的相关特性
if(f1.exists()){
System.out.println("文件名称:"+f1.getName());
System.out.println("文件的大小" + f1.length());
System.out.println("fileLastSetTime:" + f1.lastModified());
Instant instant = Instant.ofEpochMilli(f1.lastModified());
System.out.println("Instant:"+instant);
System.out.println("absolutePath:" + f1.getAbsolutePath());
System.out.println(f1.delete()?" delete successful":"delete default");
}else {
//3.若文件不存在则创建新的空文件
System.out.println(f1.createNewFile() ?"create Successful" : "create default");
}
System.out.println("---------------------");
//4.实现目录的删除和创建
File f2=new File("D:/捣乱/biu/dong/qiang");
if(f2.exists()){
System.out.println("Name:"+f2.getName());
System.out.println(f2.delete()?"delete successful":"delete default");
}else{
System.out.println(f2.mkdirs()?"directory successful":"directory default");
}
System.out.println("---------------------");
//5.获取该目录下的所有内容
File f3=new File("D:/捣乱");
File[] files = f3.listFiles();
for (File tl :files) {
String name=tl.getName();
//判断是否为文件,若是则则直接打印文件名称
if (tl.isFile()){
System.out.println(name);
}
if (tl.isDirectory()){
System.out.println("[" + name + "]");
}
}
//6.实现目录中所有内容获取的同时进行过滤
//匿名内部类的语法格式: 接口/父类类型 引用变量名 =new 接口/父类类型(){方法的重写;}
/*FileFilter fileFilter=new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".avi");
}
};*/
FileFilter fileFilter=(File pathname)->{return pathname.getName().endsWith(".avi");};
File[] files1 = f3.listFiles(fileFilter);
for (File fi:files1) {
System.out.println(fi);
}
//7.使用递归的思想获取目录以及子目录中的文件
show(new File("d:/捣乱"));
}
}