第十六章 异常机制和File类
16.1 异常机制(重点)
16.1.1 基本概念
- 异常就是“不正常”的含义,在Java语言中主要指程序执行中发生的不正常的情况
- java.lang.Throwable类是Java语言中错误(Error)hee (Exception)的超类
- 其中Error类主要用于描述Java虚拟机无法解决的严重错误
- 其中exception类主要用于因为编程错误或者偶然的外在元素导致的轻微错误,通常可以编码解决。例如0作为除数
16.1.2 异常的分类
-
java.lang.Exception类是所有异常的超类主要分为:
RuntimeException-运行时异常,也叫做非检测性异常
IOException和其他异常- 其他异常,也叫做检测行异常,所谓检测性异常就是只在编译阶段就能被编译器检测出来的异常
-
RuntimeException类的子类主要有
ArithmeticException类-算数异常
ArrayIndexOutBoundsException 数组下标越界异常
NullPointerException 空指针异常
ClassCastException类型转换异常
NumberFormatException数字格式异常
-
注意
当程序执行过程中发生异常但是又没有动手处理的时候,则由java虚拟机采用默认的方式来处理异常,而默认的处理方式就是打印异常的名称,异常发生的原因,异常发生的位置以及终止程序
16.1.3 异常的避免
- 在之后的开发中可以使用if语句来判断避免异常
- 但是会导致代码可读性差
16.1.4 异常的捕获
- 语法格式
try {
编写可能发生异常的代码;
}
catch(异常类型 引用变量名) {
编写针对该类异常的处理代码;
}
…
fifinally {
编写无论是否发生异常都要执行的代码;
}
- 注意事项
a.当需要编写多个catch分支时,切记小类型应该放在大类型的前面;
b.懒人的写法:
catch(Exception e) {}
c.fifinally通常用于进行善后处理,如:关闭已经打开的文件等。
- 执行流程
try {
a;
b; - 可能发生异常的语句
c;
}catch(Exception ex) {
d;
}fifinally {
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;
public class ExceptionCatchTest {
public static void main(String[] args) {
// 创建一个FileInputStream类型的对象与d:/a.txt文件关联,打开文件
FileInputStream fis = null;
try {
System.out.println("1");
// 当程序执行过程中发生了异常后直奔catch分支进行处理
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 (Exception e) {
e.printStackTrace();
}*/ 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 5 6 世界上...
// 当程序执行过程中发生异常又没有手动处理空指针异常时的执行流程:1 3 4 5 空指针异常导致程序终止
// 当程序执行过程中发生异常并且手动处理空指针异常时的执行流程: 1 3 4 5 世界上...
// 手动处理异常和没有处理的区别:代码是否可以继续向下执行
}
}
16.1.5 异常的抛出
注意:是否手动处理异常的区别就在于代码是否能继续向下执行
package com.lagou.task16;
public class ExceptionFinallyTest {
public static void main(String[] args) {
try {
int ia = 10;
int ib = 0;
System.out.println(ia/ib);
}catch (ArithmeticException e){
e.printStackTrace();
}finally {
System.out.println("无论是否发生异常都要运行这里");
}
System.out.println("over");//所以这个over可以执行因为异常已经被处理了。
}
}
- 基本概念
在某些特殊情况下有些异常不能处理或者不便于处理时,就可以将该异常转移给该方法的调用者,
这种方法就叫异常的抛出。当方法执行时出现异常,则底层生成一个异常类对象抛出,此时异常代码后续的代码就不再执行。
- 语法格式
访问权限 返回值类型 方法名称(形参列表) throws 异常类型1,异常类型2,…{ 方法体; }
如:
public void show() throws IOException{}
- 方法重写的原则
a.要求方法名相同、参数列表相同以及返回值类型相同,从jdk1.5开始支持返回子类类型;
b.要求方法的访问权限不能变小,可以相同或者变大;
c.要求方法不能抛出更大的异常;
- 注意:
子类重写的方法不能抛出更大的异常、不能抛出平级不一样的异常,但可以抛出一样的异常、更小的异常以及不抛出异常。
package com.lagou.task16;
public class SubExceptionMethod extends ExceptionMethod {
// @Override
// public void show() throws IOException { //子类重写的方法可以抛出和父类方法一样的异常
// super.show();
// }
//
// @Override
// public void show() throws FileNotFoundException {//子类重写的方法可以抛出更小的异常
//
// }
// @Override
// public void show() {//子类可以不抛出异常
// }
// public void show throws void ClassNotFoundException{} //子类不可以抛出和平级不一样的异常
// public void show throws Exception{}//子类不可以抛出父类异常
}
- 经验分享
若父类中被重写的方法没有抛出异常时,则子类中重写的方法只能进行异常的捕获处理。
若一个方法内部又以递进方式分别调用了好几个其它方法,则建议这些方法内可以使用抛出的方法处理到最后一层进行捕获方式处理。
16.1.6 自定义异常
- 基本概念
当需要在程序中表达年龄不合理的情况时,而Java官方又没有提供这种针对性的异常,此时就需要
程序员自定义异常加以描述。
- 实现流程
a.自定义xxxException异常类继承Exception类或者其子类。
b.提供两个版本的构造方法,一个是无参构造方法,另外一个是字符串作为参数的构造方法。
-
异常的产生
throw new 异常类型(实参);
如:
throw new AgeException(“年龄不合理!!!”);
- Java采用的异常处理机制是将异常处理的程序代码集中在一起,与正常的程序代码分开,使得程序
简洁、优雅,并易于维护。
package com.lagou.task16;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) /*throws AgeException */{
setName(name);
setAge(age);
}
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public int getAge(){
return age;
}
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();
}
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
package com.lagou.task16;
public class AgeException extends Exception {
static final long serialVersionUID = -3387516993124229948L;//序列化版本号,与序列化操作有关
public AgeException() {
}
public AgeException(String message) {
super(message);
}
}
package com.lagou.task16;
public class PersonTest {
public static void main(String[] args)/* throws AgeException*/ {
/* Person p1 = new Person("张飞", -30);
System.out.println("p1 = "+p1);*/
Person p1 = new Person("张飞",-30);
System.out.println("p1 = "+p1);
}
}
16.3 文件类(重点)
16.2.1 基本概念
- java.io.File类主要用于描述文件或者目录路径的抽象表示信息,可以获取文件或者目录的特征信息比如大小等等。
16.2.2 常用方法
方法声明 | 功能概述 |
---|---|
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() | 用于删除文件,当删除目录时要求是空目录 |
boolean createNewFile() | 用于创建新的空文件 |
boolean mkdir() | 用于创建目录 |
boolean mkdirs() | 用于创建多级目录 |
File[] listFiles() | 获取该目录下的所有内容 |
boolean isFile() | 判断是否为文件 |
boolean isDirectory() | 判断是否为目录 |
File[] listFiles(FileFilter fifilter) | 获取目录下满足筛选器的所有内容 |
package com.lagou.task16;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileTest {
public static void main(String[] args) throws IOException {
// 构造file类型的对象与d:/a.txt文件关联
File f1= new File("./aaa.txt");
// 若文件存在,则获取文件的相关特征信息并打印'
if (f1.exists()){
System.out.println("文件的名称是:"+f1.getName());
System.out.println("文件的大小是:"+f1.length());
//System.out.println("文件的最后一次修改时间"+f1.lastModified());
Date date = new Date(f1.lastModified());
SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");
String format = sp.format(f1.lastModified());
System.out.println(format);
//绝对路径:主要是指以根目录台式的路径信息如:C:/ D:/ /..
//相对路径:主要是指以当前目录所在位置开始的路径信息,如./ ../
System.out.println("文件的据对路径信息是:"+f1.getAbsolutePath());
// System.out.println(f1.delete()?"文件删除成功":"文件删除失败");
}else{
System.out.println(f1.createNewFile()?"文件创建成功":"文件创建失败");
}
// 若文件不存在。则创建新的空文件
//mkdir只能创建单层目录
System.out.println("------------------------------------------------");
File f2 = new File("./捣乱/猜猜我是谁/你猜我猜不猜/死鬼");
if (f2.exists()){
System.out.println("目录的名称是:"+f2.getName());
// 删除只能删除一级目录
System.out.println(f2.delete()?"删除成功":"删除失败");
}else{
System.out.println(f2.mkdirs()?"目录创建成功":"目录创建失败");
}
}
}
案例题目
遍历指定目录以及子目录中的所有内容并打印出来。
package com.lagou.task16;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileTest {
public static void main(String[] args) throws IOException {
构造file类型的对象与d:/a.txt文件关联
// File f1= new File("./aaa.txt");
若文件存在,则获取文件的相关特征信息并打印'
// if (f1.exists()){
// System.out.println("文件的名称是:"+f1.getName());
// System.out.println("文件的大小是:"+f1.length());
// //System.out.println("文件的最后一次修改时间"+f1.lastModified());
// Date date = new Date(f1.lastModified());
// SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss");
// String format = sp.format(f1.lastModified());
// System.out.println(format);
// //绝对路径:主要是指以根目录台式的路径信息如:C:/ D:/ /..
// //相对路径:主要是指以当前目录所在位置开始的路径信息,如./ ../
// System.out.println("文件的据对路径信息是:"+f1.getAbsolutePath());
// // System.out.println(f1.delete()?"文件删除成功":"文件删除失败");
// }else{
// System.out.println(f1.createNewFile()?"文件创建成功":"文件创建失败");
// }
若文件不存在。则创建新的空文件
mkdir只能创建单层目录
// System.out.println("------------------------------------------------");
// File f2 = new File("./捣乱/猜猜我是谁/你猜我猜不猜/死鬼");
// if (f2.exists()){
// System.out.println("目录的名称是:"+f2.getName());
删除只能删除一级目录
// System.out.println(f2.delete()?"删除成功":"删除失败");
// }else{
// System.out.println(f2.mkdirs()?"目录创建成功":"目录创建失败");
// }
// System.out.println("__________________________________");
// 将指定目录的所有东西全打印出来
File file = new File("./捣乱");
File[] list = file.listFiles();
String st=" ";
// 获取目录中所有的内容的同时进行过滤
FileFilter fileFilter = new FileFilter() {
@Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(".avi");
}
};
File[] files = file.listFiles(fileFilter);
for (int i=0;i<files.length;++i){
System.out.println(files[i].getName());
}
}
}
//打印子目录中的内容
package com.lagou.task16;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileTest {
// 自定义成员方法实现指定目录以及子目录中所有内容的打印
public static void show(File file){
File[] files = file.listFiles();
for (File tf: files){
String name = tf.getName();
if (tf.isFile()){
System.out.println(name);
}
if (tf.isDirectory()){
System.out.println("["+name+"]");
show(tf);
}
}
}
public static void main(String[] args) throws IOException {
System.out.println("===========================");
show(new File("./捣乱"));
}
}