异常处理和File类-11月16日讲课内容
异常
Throwable 类
Throwable 类是Java语言中所有错误和异常的顶级父类,直接子类为 Error 和 Exception
构造方法
// 无参构造:构造一个新的 throwable 对象,其详细信息为null
public Throwable()
// 有参构造:使用指定的详细信息(message)构造一个新的 throwable 对象
public Throwable(String message)
成员方法
// 返回此 throwable 对象的详细信息字符串
public String getMessage()
// 返回一个简要信息描述
public String toString()
// 打印此 throwable 对象及其详细信息字符串到标准错误流(控制台)
public void printStackTrace()
案例代码
public class Test {
public static void main(String[] args) {
Throwable throwable1 = new Throwable();
System.out.println(throwable1.getMessage());
System.out.println(throwable1.toString());
throwable1.printStackTrace();
Throwable throwable2 = new Throwable("错误信息!!!");
System.out.println(throwable2.getMessage());
System.out.println(throwable2.toString());
throwable2.printStackTrace();
}
}
Error
Error 类是 Throwable 的子类,它指出了一个合理的应用程序不应该试图捕捉的严重问题
【注意】Error 结尾的是严重问题,无法解决
Exception
Exception 类及其子类是一种 Throwable 的子类,指示了一个合理的应用程序可能想要捕获的条件。
【注意】Exception 结尾的是我们可以处理的,一般我们需要关注的是 RuntimeException
异常处理
异常处理分为两种:捕获和抛出
有能力处理就进行捕获,没有就抛出
捕获
格式:
try {
// 有可能出现问题的代码,存在一定隐患的代码
} catch (异常类型 变量名) {
// 对应当前异常类型的处理方式
} finally {
// 无论是否捕获,都会执行,常用于释放资源
}
案例代码
public class Test {
public static void main(String[] args) {
int num1 = 0;
int num2 = 20;
int ret = 0;
/*
* 除数不能为0
*/
try {
ret = num2 / num1;
} catch (ArithmeticException e) {
e.printStackTrace();
}
System.out.println(ret);
}
}
结果
java.lang.ArithmeticException: / by zero
at code.exception.Test.main(Test.java:11)
0
【注意】
1、代码中出现异常,JVM会终止代码运行,如果使用try catch捕获处理异常,JVM会认为当前代码中不存在异常,可以继续运行。 2、try - catch代码块中声明的都是局部变量,需要提前声明 3、try - catch捕获处理异常,可以处理多种异常情况 4、代码中存在多种隐患,存在多个异常情况,try - catch捕获有且只能处理第一个出现异常的代码,因为JVM从异常代码开始直接进入异常捕获阶段 5、Exception作为Java中所有异常的超类,在捕获异常处理时如果直接使用Exception进行捕获处理,无法具体到对某一个异常来处理 6、Exception可以作为try - catch 最后一个,用于处理其他异常捕获之后没有对症方式遗留问题
抛出
关键字:
throw
在方法内特定条件下抛出指定异常,后面跟异常类型的对象
throws
在【方法声明】位置,告知调用者,当前方法有哪些异常抛出,后面跟异常的类型
用于处理非当前方法操作问题,导致出现的异常,一般情况下是用于处理方法运行过程中因为参数传入,参数处理,运算结果导致的问题,抛出异常。
throw是一个稍微高级的参数合法性判断
案例代码
public class TestThrows {
public static void main(String[] args) {
try {
test(1, 0);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
/**
* 测试方法,打印两个数的差
*
* @param num1 第一个参数,被除数
* @param num2 第二个参数,除数
* @throws ArithmeticException 如果除数为0,抛出异常
*/
public static void test(int num1, int num2) throws ArithmeticException {
if (0 == num2) {
throw new ArithmeticException("除数不能为0");
}
System.out.println(num1 / num2);
}
}
结果
java.lang.ArithmeticException: 除数不能为0
at code.exception.TestThrows.test(TestThrows.java:23)
at code.exception.TestThrows.main(TestThrows.java:7)
【注意】
1、throw 和 throws 必须同时出现,并且体现在注释上
2、代码如果运行到throw抛出异常,之后的代码不再运行,之后的代码是成为无法抵达的代码
3、代码中存在多种隐患,按照隐含的情况,分门别类处理,不能在同一个条件内抛出两个异常。并且在方法的声明位置,throws之后,不同的异常,使用逗号隔开
4、当调用带有异常抛出的方法时,对于方法抛出的异常,有两种处理方式,可以捕获处理,也可以抛出处理。
异常分类
运行时异常
RuntimeException:代码运行过程中出现的异常,没有强制处理的必要性,因为JVM会处理RuntimeException异常,即报错
其他异常
强制要求处理,不管是捕获处理还是抛出处理,都需要进行操作,如果未处理就会报错
自定义异常
继承自 Exception 或者 RuntimeException,只需要提供无参构造和一个带参构造即可
【注意】如果继承自Exception,调用抛出了此异常的方法需要手动对其捕获或者抛出
自定义异常类
public class MyException extends Exception {
public MyException() {}
public MyException(String message) {
super(message);
}
}
测试
public class Test {
public static void main(String[] args) {
try {
buy(false);
} catch (MyException e) {
e.printStackTrace();
}
}
/**
* 买方法,当没有女朋友的时候,抛出异常
* @param hasGirlFriend boolean类型,是否有女朋友
* @throws MyException 自定义单身狗异常
*/
public static void buy(boolean hasGirlFriend) throws MyException {
if (false == hasGirlFriend) {
throw new MyException("你还没有女朋友");
}
System.out.println("买一送一");
}
}
结果
code.myexception.MyException: 你还没有女朋友
at code.myexception.Test.buy(Test.java:19)
at code.myexception.Test.main(Test.java:6)
注意
1、父类的方法有异常抛出,子类的重写方法在抛出异常的时候必须要小于等于父的异常
2、父类的方法没有异常抛出,子类的重写方法不能有异常抛出
3、父类的方法抛出多个异常,子类的重写方法必须比父少或者小
总结
1、异常的存在是非常有必要的,可以帮助我们定位和解决问题
2、异常的处理方式:捕获和抛出
3、自定义异常一定要有无参构造和有参构造
4、后期会遇到大量的异常,一般使用快捷键就能搞定
Eclipse:Ctrl + 1
Idea:Alt + Enter
File 类
文件和目录路径名的抽象表示形式,提供了对文件和文件夹的增删改查的方法
构造方法
File(String pathName);
根据指定的文件路径,或者文件夹路径,创建对应的File类对象。路径可以是相对路径,可以是绝对路径
File(String parent, String childName);
根据指定的父目录文件夹路径,和子文件或者子文件夹的名字,创建对应的File类对象
File(File parent, String childName);
根据指定的父目录File类对象,和子文件或者子文件夹的名字,创建对应的File类对象
【注意】如果是文件必须要有后缀名,否则就是文件夹
案例代码
public class Test {
public static void main(String[] args) {
File file1 = new File("D:/aaa");
File file2 = new File("D:/aaa", "1.txt");
File file3 = new File(file1, "1.txt");
System.out.println(file1); // D:\aaa
System.out.println(file2); // D:\aaa\1.txt
System.out.println(file3); // D:\aaa\1.txt
}
}
创建方法
boolean createNewFile();
通过File类对象调用,创建File类对象中对应地址的普通文件,创建成功返回true,创建失败返回false;
失败原因:
1. 路径不合法,路径不存在,路径错误。
2. 对应文件夹没有写入权限。
3. 对应文件已存在。
4. 磁盘坏道,电脑蓝屏。
boolean mkdir();
通过File类对象创建,创建File类对象中对应的文件夹,创建成功返回true,失败返回false
失败原因:
1. 路径不合法,路径不存在,路径错误。
2. 对应文件夹没有写入权限。
3. 对应文件夹已存在。
4. 磁盘坏道,电脑蓝屏。
boolean mkdirs();
创建文件夹过程中可以完成中间路径
boolean renameTo(File dest);
通过File类对象调用,转为目标dest指定File类对象,可以操作普通文件,可以操作文件夹。移动或者重命名
案例代码
public class Test {
public static void main(String[] args) throws IOException {
File file1 = new File("C:/Users/CJF/Desktop/啥啥啥.txt");
boolean createNewFile = file1.createNewFile();
System.out.println(createNewFile);
File file2 = new File("C:/Users/CJF/Desktop/啥啥啥");
boolean mkdir = file2.mkdir();
System.out.println(mkdir);
File file3 = new File("C:/Users/CJF/Desktop/啥啥啥/afaf/aggr/htedfgb/er");
boolean mkdirs = file3.mkdirs();
System.out.println(mkdirs);
File file4 = new File("C:/Users/CJF/Desktop/什么鬼.txt");
boolean renameTo = file1.renameTo(file4);
System.out.println(renameTo);
}
}
删除方法
boolean delete();
通过File类对象调用,删除File类对象对应的文件或者文件夹。
注意事项:
1. 从磁盘中直接抹掉数据,不经过回收站,慎用
2. 删除操作只针对于空文件夹操作,不能删除非空文件夹
void deleteOnExit();
程序退出之后,删除调用该方法File类对象,对应的普通文件或者文件夹。
用于缓冲文件,缓存问题,日志文件
案例代码
public class Test {
public static void main(String[] args) throws IOException {
File file = new File("C:/Users/CJF/Desktop/Test.txt");
System.out.println(file.createNewFile()); // true
System.out.println(file.delete()); // true
file.deleteOnExit();
}
}
获取方法
前三个方法和文件或者文件夹是否存在无关。
String getPath();
获取File类对象中保存的路径
String getName();
获取File类对象操作对应的文件名或者文件夹名
String getParent();
获取File类对象操作文件或者文件夹的上级目录
String getAbsolutePath();
获取当前File类对象对应路径的绝对路径
long length();
获取当前【文件】的占用磁盘空间字节数
根据不同的系统环境,文件夹调用length方法 0L 或者 4096L
long lastModified();
获取当前文件夹上一次修改时间的【时间戳】
是从计算机元年1970-01-01 00:00:00 到修改时间的秒数
案例代码
public class Test {
public static void main(String[] args) {
File file = new File("D:/aaa/bbb/ccc/1.txt");
System.out.println(file.getPath()); // D:\aaa\bbb\ccc\1.txt
System.out.println(file.getParent()); // D:\aaa\bbb\ccc
System.out.println(file.getName()); // 1.txt
System.out.println(file.length()); // 0
System.out.println(file.lastModified());// 0
System.out.println(new File(".").getAbsolutePath()); // D:\Qfeng\day27\.
}
}
判断方法
boolean isFile();
判断当前File类对象对应的是不是普通文件。
boolean isDirectory();
判断当前File类对象对应的是不是文件夹。
boolean exists();
判断当前File类对象对应的内容是否存在。
boolean isAbsolute();
判断当前File类对象保存的路径是不是绝对路径。
boolean isHidden();
判断当前File类对象对应的文件是不是一个隐藏文件。
案例代码
public class TestFileDecide {
public static void main(String[] args) {
File file = new File("D:/Adobe");
System.out.println(file.exists()); // true
System.out.println(file.isFile()); // false
System.out.println(file.isDirectory()); // true
System.out.println(file.isAbsolute()); // true
System.out.println(file.isHidden()); // false
}
}
列表方法
static File[] listRoots();
获取Windows操作系统下的所有盘符
Linux中没有什么作用。
String[] list();
获取File类对象对应文件夹中所有子文件或者子文件夹名字,String类型数组
File[] listFiles();
获取File类对象对应文件夹中所有子文件或者子文件夹的File类对象数组
案例代码
public class Test {
public static void main(String[] args) {
File file = new File("C:/Users/CJF/Desktop");
String[] list = file.list();
for (String fileName : list) {
System.out.println(fileName);
}
File[] listFiles = file.listFiles();
for (File file2 : listFiles) {
System.out.println(file2);
}
File[] listRoots = File.listRoots();
for (File file2 : listRoots) {
System.out.print(file2 + "\t"); // C:\ D:\ E:\
}
}
}
FilenameFilter 文件名过滤器接口
实现此接口的类实例可用于过滤文件名。
boolean accept(File dir, String name);
dir是当前操作获取文件列表的文件夹File类对象
name是当前文件夹下的文件名或者文件夹名
案例代码
public class Test {
public static void main(String[] args) {
File file = new File("D:/EclipseWorkSpace/rx1901/src/com/fc/za/file");
String[] fileNameArray = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile() && name.endsWith(".java");
}
});
for (String fileName : fileNameArray) {
System.out.println(fileName);
}
}
}
扩展:匿名内部类格式
匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与内部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类
不使用匿名内部类
public class Demo7 {
public static void main(String[] args) {
File file = new File("D:/EclipseWorkSpace/rx1901/src/com/fc/za/file");
// 传入一个接口的实现类
String[] list = file.list(new JavaFilter());
// 对结果进行增强for循环
for (String string : list) {
System.out.println(string);
}
}
}
// 此接口用于过滤指定的文件名,需要重写accept方法
class JavaFilter implements FilenameFilter {
// 过滤以 .java 结尾的文件
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile() && name.endsWith(".java");
}
}
使用匿名内部类
public class Demo7 {
public static void main(String[] args) {
File file = new File("D:/EclipseWorkSpace/rx1901/src/com/fc/za/file");
/*
* 匿名内部类,常用于我们的参数传递,
* 用来创建一个没有名字的类的对象
*
* 写法:new 类名或者接口名() {}
*
* 如果是接口,直接在{}里面实现方法的重写
*/
String[] list2 = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return new File(dir, name).isFile() && name.endsWith(".java");
}
});
for (String string : list2) {
System.out.println(string);
}
}
}