异常
java 异常是程序运行过程中出现的错误。Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。在Java中定义了许多异常类,分为两大类,错误Error和异常Exception。
异常的组成
Throwable 是所有异常的超类。
Error 该类的错误是无法通过Java处理解决的。
Exception 该类是我们平时所指的异常,它有很多的子类。可以通过Java处理进行解决。
RunTime Exception 是Exception的子类,是程序在运行时发生的异常。
异常的分类
- 严重错误Error。
- 编译异常 Exception 如语法错误、IO异常等,可以通过处理解决。
- 运行时异常 RunTime Exception 是如数学异常,可以不处理。
异常的基本操作
- 创建异常对象(JDK已定义的异常会自动创建对象,自定义异常需要手动创建)
- 抛出异常(JDK已有定义的异常会自动抛出异常,自定义异常需要手动抛出)
- 处理异常:
捕获处理,将异常获取,使用try/catch做分支处理
try{
需要检测异常的代码块;
} catch(异常对象) {
异常处理代码
可以调用异常的方法
通常我们只使用一个方法:printStackTrace打印异常信息
}
声明抛出处理,出现异常后不处理,声明抛出给调用者处理。
方法声明上加throws 异常类名
try{}:用来捕捉异常。
catch():用来处理异常。
异常对象:表示处理哪类异常。
finally:只能加入到 catch语句块后,并且与try catch连用,无法单独使用。表示无论异常是否发生,都执行。
注意:
- 异常处理,指处理的一种可能性,即有了异常处理的代码,不一定会产生异常。如果没有产生异常,则代码正常执行,如果产生了异常,则中断当前执行代码,执行异常处理代码。
- catch中定义的异常对象,表示只会捕捉到定义好的异常对象或异常对象的子类,其它类的异常则不会被捕捉到。
throws/throw 关键字
thorws表示如果代码中出现了Java必须要求我们进行异常处理的代码(文件流),而我们没有进行异常处理,那么对应的方法就需要增加throws关键字。表示该方法的异常会抛给方法的调用者。
throw 用来创建异常,可以创建Java定义好的异常类,也可以是我们自定义的异常类。
异常的注意事项
- 多异常处理
捕获处理:
1多个异常分别处理
2多个异常一次捕获多次处理
3多个异常一次捕获一次处理
- 运行时异常被抛出可以不处理。即不捕获也不声明抛出
- 如果父类抛出了多个异常,子类覆盖父类方法时,只能抛出相同的异常或者是他的子集
- 父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
- 当多异常处理时,捕获处理,前边的异常类不能是后边异常类的父类
- 在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收。方法中已经出现返回语句返回值A,再在finally中修改A值,则最终的返回值仍为修改前A的值。但在该方法中A的值已经被修改了
自定义异常
如果Java中没有我们需要的异常,我们可以自己定义特殊的异常类。
步骤:
- 创建异常类并继承Exception(编译异常)/RuntimeException(运行时异常)。
- 进行异常处理。
常见异常
运行时异常:
- IndexOutOfBoundsException 索引越界异常
- ArithmeticException:数学计算异常
- NullPointerException:空指针异常
- ArrayOutOfBoundsException:数组索引越界异常
- ClassNotFoundException:类文件未找到异常
- ClassCastException:造型异常(类型转换异常)
编译异常:
- IOException、文件读写异常
- FileNotFoundException:文件未找到异常
- EOFException:读写文件尾异常
- MalformedURLException:URL格式错误异常
- SocketException:Socket异常
- SQLException:SQL数据库异常
文件流
File
Java中的File类用来描述文件,每一个File就代表硬盘上的一个文件或一个文件夹。
File的构造器
public File(String pathname); 通过文件/文件夹路径方式获取File对象。
pathname 可以是一个文件的全路径或是一个文件夹的路径。
文件路径/文件夹路径可以是相对路径也可以绝对路径。Eclipse中相对路径的参照物是当前工作空间下对应项目的根路径。为了避免出现路径异常,增加程序的不稳定性,通常都写绝对路径。
File普通方法
File对象中提供了很多获取文件信息的方法和操作。
String getPath(); // 获取文件的路径。
String getName(); // 获取文件的文件名。
long length(); // 获取文件的大小(字节)。
boolean exists(); // 文件是否存在 true/false=存在/不存在。
boolean isFIle(); // 判断是否是文件 。
boolean isDircectory(); // 判断是否是文件夹。
boolean mkdirs(); // 创建文件夹。
boolean createNewFile(); // 创建文件,文件不存在创建,存在不做任何事。
boolean delete(); // 删除(删除文件夹时,文件夹必须为空)。
File[] listFiles(); // 获取一个目录下的子文件和子文件夹(不包括子文件夹下的内容)。
IO
所谓的IO就是input(输入)/output(输出),Java的IO都在java.io包下,java.io几乎包含了所有操作输入输出的类。通过Java的IO可以将数据持久化到某个文件内或将某个文件读取到内存中。
分类
按照流的走向可以分为输入流和输出流。
按照流读取的单位可以分为字节流和字符流。
字节转换:
字节是一种计量单位(Byte)。
1KB = 1024B(字节)
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
字符转换:
字符是一种表现形式。
英文、英文标点 = 1字节
中文、中文标点 = 2字节
不同的编码字符占用的字节数也不同如:
Ascil编码:中文占用2个字节。
UTF-8编码:中文占用3个字节。
字节流
在数据传输过程中,一切数据(文本、图像、声音等)最终存储的均为一个个的字节,即二进制数字。所以数据传输过程中使用二进制数据可以完成任意数据的传递。
字节输入流InputStream(抽象类,超类)
FileInputStream 操作文件的字节输入流。
构造器:
public FileInputStream(String name);
name表示需要读取文件的路径。
public FileInputStream(File file);
常用方法:
int available();// 获取文件的字节数(同File.length()获取到的相同)
int read(); // 读取一个字节的数据,读到末位返回-1
int read(byte[] b); // 读取一个字节数组,读到末位返回-1
void close(); // 关闭流
字节输出流 OutputStream(抽象类,超类)
FileOutputStream 操作文件的字节输出流。
构造器:
public FileOutputStream(String name);(覆盖)
name表示需要写出的文件的存放路径。
public FileOutputStream(String name, boolean append);
append=true表示追加覆盖
public FileOutputStream(File file);
public FileOutputStream(File file, boolean append);
常用方法:
write(int n); // 输出一个字节;(使用int替代了byte)
write(byte[] b); // 输出一个字节数组;
write(byte[] b, int off , int len); // 输出字节数组的一部分;
void close(); // 关闭流
字符流
在IO开发过程中,我们传输最频繁的数据为字符,而以字节方式传输字符需要每次将字符串转换成字节再处理,而且也丧失了程序员对数据内容的判断(因为程序员只认识字符,不认识字节)。所以,为了让程序员方便对字符进行操作,Java提供了专门以字符作为操作单位的类——字符流,其底层仍然为字节流。
显然,字符流只能操作字符,无法操作其他数据,如声音、视频等。
字符输入流 Reader(抽象类,超类)
FileReader 用来操作文件的字符输入流(简便的流)
构造器:
public FileReader(String name)
name表示文件读取的路径
public FileReader(File file)
file 表示要读取的文件
常用方法:
int read(); // 读取一个字节的数据,读到末位返回-1
int read(char[] c); // 读取一个字符数组
void close(); // 关闭流
字符输出流 Writer(抽象类,超类)
FileWriter 用来操作文件的字符输出流(简便的流)
构造器:
public FileWriter (String name);(覆盖)
name表示需要写出的文件的存放路径。
public FileWriter (String name, boolean append);
append=true表示追加覆盖
public FileWriter (File file);
public FileWriter (File file, boolean append);
常用方法:
write(int n); // 输出一个字符;(使用int替代了char)
write(char[] c); // 输出一个字符数组;
write(char[] b, int off , int len); // 输出字符数组的一部分;
write(String s):输出一个字符串
write(String s , int off , int len):输出字符串的一部分
flush():刷新缓冲区,将内容写出到指定IO资源
void close(); // 关闭流
高效流
高效流就是将字节流和字符流进行了包装,所以普通流中的方法高效流都存在,而高效流在普通流的基础上又添加了新的功更为强大的方法,且添加了缓冲区效率也更高。这相当于将普通流进行了包装,让原有类的功能变得更为强大。
高效字节流:BufferedInputStream/BufferedOutputStream
高效字符流:BufferedReader/BufferedWriter
新增常用方法:
String readLine(); // 按行读取
void newLine(); // 创建新一行,写入时用
字节流和字符流区别
- 读取单位不同,字符流按照字符的字节数读取或写入。
- 字节流可以操作任何形式的数据、字符流只可以操作文本数据。
编码表
常见编码表:
名称 | 说明 |
GBK/GB2312 | 中文环境默认码表,中文码表(2个字节对应一个汉字) |
UTF-8 | 万国码,JavaEE项目中的通用编码表,包含各国文字编码(一般3个字节对应一个汉字) |
ISO8859-1 | 拉丁码表,不包含中文,是西方较通用的码表 |
编码的使用:
- 乱码:当字符与字节转换过程中使用了不同的码表,会造成乱码的情况。
- 字符串:当我们将字符串转为对应的数字字节时,需要指定码表,则存储了为该字符该码表对应的数字字节,如果使用了其他码表重写翻译回字符串,则拼写的新字符串会乱码。
- IO:与字符串编码表使用类似,当以某个码表写出字节数据时,又使用另外码表展示,会出现乱码。