一、异常引言
程序出现的不正常的情况。异常就是Java程序在运行过程中出现的错误。
问题也是现实生活中一个具体事物,也可以通过java 的类的形式进行描述,并封装成对象。其实异常就是Java对不正常情况进行描述后的对象体现。
二、异常继承体系图解
三、异常的体系
java.lang.Throwable类
|--Error 严重问题,我们不处理。要改正代码。
通常出现重大问题如:运行的类不存在或者内存溢出等。
是不需要增加代码处理(try...catch)的。代码本身有问题。
一般这种情况是需要修改代码的。一般的处理方案是加内存,将这类补上来。
|--Exception
|--RuntimeException
运行期异常,我们也不处理(try...catch)。代码不够严谨,我们需要修正代码。
比如:传递的参数(别人传过来)。参数类型不正确等,非空校验?
|--非RuntimeException
编译期异常,即编写代码报红×的,必须处理的,否则程序编译不通过
将来有可能出现的异常情况。
隐含的问题,不管怎么修改代码都会隐含,必须处理
编译时异常和运行时异常的区别
Java中的异常被分为两大类:编译时异常和运行时异常。
所有的RuntimeException类及其子类的实例被称为【运行时异常】,
其他的非RuntimeException异常及其子类就是【编译时异常】
【编译时异常】
Java程序必须显示处理( try catch 或throws),否则程序就会发生错误,无法通过编译
【运行时异常】
无需显示处理,也可以和编译时异常一样处理,可处理可不处理。
声明抛出为RuntimeException的方法被其他对象调用时,是不需要try...catch或者throws的。即使声明了,再调用时也是不需要处理。
代码不够严谨,我们需要修正代码。
注意:
每种体系的子类都是以父亲的名称作为后缀。
* XxxError
* XxxException
四、异常的处理:
A:JVM的默认处理方式
如何程序出现了问题,我们没有做任何处理,最终jvm会做出默认的处理。
把异常的名称,原因,位置等【信息输出在控制台】,同时会【结束程序】。
一旦有异常发生,【其后来的代码不能继续执行】。
举例:
Exception in thread "main" java.lang.ArithmeticException: / by zero
【其后来的代码不能继续执行】。
B:如果程序有异常,我们自己怎么手动解决呢?
方式a:编写处理代码try...catch...finally
自己编写处理代码后,即使发生了异常,后面的程序可以继续执行
基本格式:
try{
可能发生异常的代码; (包裹的代码越少效率越高)
}catch(异常类名 变量名){
异常的处理代码;
//处理完后,异常代码其下面的代码可以继续操作
//,实际开发中返回一个错误页面。
}finally{
释放资源的代码;
}
变形格式:
1)try...catch:
try {
可能出现问题的代码;
}catch(异常名 变量) {
针对问题的处理;
}
2)try...catch...catch
3)try...catch...finally
4)try...catch...catch...finally
5)try...finally
注意
A:try里面的代码越少越好
B:catch里面必须有内容,哪怕是给出一个简单的提示(如输出语句或者e.printStackTrace())
C:一旦try代码块中有异常发生,匹配到catch中的异常类型,就会立马执行catch里面的代码。
1.一旦try里面出了问题,jvm会帮我们生成一个异常对象,然后把这个对象抛出,
然后和catch里面的问题进行匹配,
2.一旦有匹配的该对象类型,就执行catch里面的处理信息,然后结束了try...catch,
继续执行该try...catch后面的语句。
一个代码中,有多个异常问题,怎么解决呢?
A:一个个用异常处理方案解决。
每一个问题写一个try...catch:
try{
可能出现问题的代码;
}catch(异常类名 变量名){
针对问题的处理;
}
try{
...
}catch( ){
...
}
......
B:针对所有问题,写一个try...多个catch代码。
写一个try,多个catch
try{
...
}catch(异常类名 变量名) {
...
}catch(异常类名 变量名) {
...
}
......
注意事项
1:能明确的异常类型尽量明确,不要用大的异常类型来处理。
2:平级关系的异常catch谁前谁后无所谓,
如果多个异常出现了子父关系,父异常【必须】在后面。
否则,因为多态,永远匹配不到子异常。
JDK7针对多个catch进行了优化:
多个catch用一个catch替代。不是指多个catch的内容,用一个Exception处理。
格式:
catch(异常1 | 异常2 | 异常3 ... 变量){...}
注意:
A:处理方式是一致的。(实际开发中,好多时候可能就是针对同类型的问题,给出同一个处理)
B:这些异常必须是平级关系。
和try...catch...catch的不同点是:
JDK7的这种方案是必须平级关系,不能有子父关系。
而try...catch...catch父亲放最后是可以的
最终的标准代码格式
基本格式:标准代码
try{
可能有问题的代码
}catch(异常类名 变量名){
处理方案↓:
变量名.printStackTrace();
}finally{
释放资源。(数据库,IO)
}
finally:里面代码永远会执行。但有特殊情况。
如果在执行到finally之前jvm退出了(System.exit(int number)),就不能执行了。
方式b:抛出throws
把自己处理不了的,在方法上声明,告诉调用者,这里有问题调用者去处理该异常。
【出错后下面的代码不在继续执行】。
而try catch处理后,出错位置后面的代码还是会执行的
处理方式:用throws关键字在方法上声明(抛出异常)。
c:到底使用谁?
a:能自己处理的尽量自己处理。(建议用try...catch)
b:实在不行,你先抛了在说。其实我们对异常是进行统一处理的。
看到问题,于问题提示处或者行号位置点击鼠标,提示解决方案
点击左边红X即可。处理方案就出来了实际开发用第二种try...catch。
五、自定义异常
java虽然已经考虑到了很多种异常情况,但是,有些需求java程序是考虑不到的。
比如说:我要求学生的分数不能为负数。那么,针对这种情况,我们就要编写自定义异常类进行处理。
如何编写一个自定义异常类呢?
就是自定义一个类,继承自Exception或者RuntimeException,
【只需要提供无参构造和一个带参构造即可】
【开发中】:一般继承自RuntimeException。
异常的注意实现
A:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。
(父亲坏了,儿子不能比父亲更坏)
B:如果父类抛出了多个异常,子类重写父类时,
只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
C:如果被重写的方法没有异常抛出,
那么子类的方法绝对不可以抛出异常,
如果子类方法内有异常发生,那么子类只能try...catch,不能throws
六、java.io.File类(掌握)
引言
* 我们要想实现IO的操作,就必须知道硬盘上文件的表现形式。
* 而Java就提供了一个类File供我们使用。
概述
IO流操作中,大部分都是对文件的操作,所以Java就提供了File类供我们来操作文件。
public class File extends Object implements Serializable, Comparable
File是【文件】和【目录】路径名的抽象表示形式。
直接打印file,打印出路径,说明重写了toString()方法
IO用于在设备间进行数据传输的操作
IO流分类:
A:流向
输入流 读取数据
输出流 写出数据
B:数据类型
字节流
字节输入流
字节输出流
字符流
字符输入流
字符输出流
注意:
a:如果我们没有明确说明按照什么分,默认按照数据类型分。
b:除非文件用windows自带的记事本打开我们能够读懂,才采用字符流,否则建议使用字节流。
构造方法
A:File(String pathname):
根据一个路径字符串得到File对象
举例:File file = new File("e:\\demo\\a.txt"); // 【常用方式】
B:File(String parent, String child):
根据一个目录和一个子文件/目录得到File对象
举例:File file = new File("e:\\demo","a.txt");
C:File(File parent, String child):
根据一个父File对象和一个子文件/目录得到File对象
举例:
File file = new File("e:\\demo");
File file2 = new File(file,"a.txt");
注意:
三个构造方法的效果都一样
引用变量仅仅是一个路径的表示,不代表具体的路径一定是存在的。
功能方法
A:创建功能
创建文件:
public boolean createNewFile()
如果指定的文件不存在,就创建,返回true。
如果存在这样的文件,
就不创建,返回false
创建文件夹:
public boolean mkdir()
创建文件夹
如果存在这样的文件夹,就不创建了
创建多级目录
如果想创建一个指定的目录或者文件,要求,父目录必须存在。
public boolean mkdirs() // 【常用方式】
创建文件夹,如果存在,就不创建。
这个时候,如果父文件夹不存在,它也会自动创建
注意:
你要创建什么,自己最清楚。
也就是,你要调用哪个方法,你自己必须明白
因为如果你不明白,就会有问题。
绝对路径与相对路径
绝对路径:以盘符开始的路径
相对路径:不以盘符开始的路径。
除非你知道相对于那个文件夹。为了方便,会使用。
如果你创建文件或者文件夹忘了写盘符路径,那么,默认在项目路径下。
"file.txt"可以是一个文件名,也可以是一个文件夹名。
书写格式错误:
盘符:后面没有双斜杠
格式书写错误 F:后面没有双斜杠
如果File对象的根目录( F:)与当前项目所在盘符一致,那么就会在该程序或该程序包所在目录创建文件或文件夹。
如果File对象的根目录( F:)与当前项目所在盘符不一致,就会在该根目录下创建文件或文件夹(按正常理解即可)
B:删除功能
public boolean delete():
既可以删除文件,也可以删除文件夹,取决于使用的对象
文件对象调用就删除文件;文件夹对象调用就删除文件夹
注意:
A:如果你删除的文件夹下还有内容,那么必须先把使用内容删除完毕后,在删除该文件夹
B:java语言的删除不走回收站
C:重命名功能
public boolean renameTo(File dest)
如果File路径名相同,就是改名。
如果File路径名不同,就是改名并剪切到目的路径。
D:判断功能【常用·掌握】
public boolean exists()
判断file对象是否存在(此抽象路径名表示的文件或目录是否存在。)
public boolean isFile()
判断file对象是否是文件
public boolean isDirectory()
判断file对象是否是文件夹
public boolean isAbsolute()
判断file对象是否是绝对路径
public boolean canRead() // windows下默认所有文件都是可读的
判断file对象是否可读
public boolean canWrite()
判断file对象是否可写
public boolean isHidden()
判断file对象是否隐藏
注意:
File对象路径中文件或文件夹不存在时,全部返回false;
如果存在的话,根据文件或者文件夹的实际属性返回实际的值
E:获取功能【】
获取file对象的绝对路径
public String getAbsolutePath()
获取相对路径
public String getPath()
获取文件名称
public String getName()
获取文件的大小,单位是字节
public long length()
获取上次修改时间的毫秒值
public long lastModified()
注意:
文件或文件夹存不存在都会根据file对象返回对象的属性
F:高级获取功能
public static File[] listRoots()
列出可用的系统文件根目录 c:\\ 或者d:\\
无须关联file,电脑本身存在与File中的参数无关
返回的是指定目录下所有文件或者文件夹的【文件名称数组】
public String[] list()
返回的是指定目录下所有文件或者文件夹【对象数组】
public File[] listFiles()
注意:对目录操作
G:文件名称过滤器接口FilenameFilter
FilenameFilter 一般使用匿名内部类实现。
public String[] list(FilenameFilter filter)
文件名称过滤
public File[] listFiles(FilenameFilter filter)
看源码解析
boolean accept(File dir,String name)
指定文件路径是否应该包含在某一文件列表中。
dir - 被找到的文件所在的目录。
name - 文件的名称。
返回:
当且仅当该名称应该包含在文件列表中时返回 true;
否则返回 false。
String[] strArray = file.list(newFilenameFilter() {
@Override
publicbooleanaccept(File dir, String name) {
// return false;
// return true;
//通过这个测试,我们就知道了,到底把这个文件或者文件夹的名称加不加到数组中,取决于这里的返回值是true还是false
//所以,这个的true或者false应该是我们通过某种判断得到的
// System.out.println(dir + "---" + name);
// File file = new File(dir, name);
// // System.out.println(file);
// boolean flag = file.isFile();
// boolean flag2 = name.endsWith(".jpg");
// return flag && flag2;
returnnewFile(dir, name).isFile() && name.endsWith(".jpg");
}
});