1.异常
异常:程序中出现的一些程序处理不了的特殊情况。异常类 Exception
之前见过的几种异常类型有NullPointerException,ArrayIndexoutofBoundsException, ClasscastException,以及数学运算异常ArithmeticException
当程序中出现异常,就会中断程序,代码不会继续运行,这时候就需要处理异常
在main函数中写如下代码,会报出空指针异常NullPointerException
String str= null;
System.out.println(str.length());//这时会报出空指针异常
写如下代码,会报出数学运算异常ArithmeticException
int i=12;
int a=0;
System.out.println(i/a);//这时会报出数学运算异常
1.异常的分类:检查性异常、运行时异常
1检查时异常(编译异常,需要try catch处理的异常):在编写代码时就会抛出的异常(代码上会报错),需要在代码中编写处理方式(和程序之外的资源进行访问)
检查时异常的类直接继承Exception
File file = new File("D:\\easy.txt");//电脑里不一定有,只是这样写
FileInputStream fis =null;
2运行时异常:在代码运行阶段可能会出现的异常,可以不用明文处理 ,可以通过代码避免异常的发生(做判断)
运行时异常的类继承自RuntimeException(是Exception的子类)
以下是我们在编写代码时自行规避运行时异常的情况:
int i=12;
int a=0;
if (a==0){
System.out.println("0不能做除数");
}else {System.out.println(i/a);}
2.处理异常的方式:try...catch...finally
try块尝试捕获异常,catch代码块是捕捉到异常后要处理的代码,finally代码块是无论是否出现异常,都会执行的代码块(一般用在关闭链接,关闭流等等)
try {
//try块尝试捕捉异常 块中是可能会抛出异常的代码
} catch (FileNotFoundException e){
//catch代码块就是捕捉到异常后要处理的代码
System.out.println("11");
}finally {
//无论是否出现异常,都会执行的代码块
//一般用在关闭资源(关闭链接、关闭流等等)
System.out.println("22");
}
3.try...cacth...finally的一个实例
File file = new File("C:\\easy.txt");//电脑里不一定有,只是这样写
FileInputStream fis =null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e){
//e.printStackTrace();//打印异常日志
System.out.println("11");
}finally {
if (fis!=null){//if这里是要判断流是否关闭,如果未关闭则需要关闭流
try {
fis.close();
} catch (IOException e) {
//e.printStackTrace();//打印异常日常
}
}
System.out.println("22");
}
4.下面的实例为如果一个try代码块中可能出现多种异常的一种处理方式
try代码块中可能出现数学运算异常ArithmeticException
类型错误异常ClassCastException
文件搜索异常FileNotFoundException
面对这三种异常,可以写出三个catch语句块,在每一个catch中逐个填入出现的异常类型。
//try块中可能有多种异常
try{
System.out.println(12/0);
Object strA = "";
System.out.println((Integer) strA);
fis=new FileInputStream(file);//本try块中有可能出现三种不同的异常
}catch (ArithmeticException e){
//出现数学运算异常ArithmeticException要执行的代码
System.out.println("出现ArithmeticException");
}catch (ClassCastException c){
System.out.println("出现ClassCastException");
}catch (FileNotFoundException f){
System.out.println("出现FileNotFoundException");
}finally {
if (fis!=null){
try{
fis.close();
}catch (IOException o){
o.printStackTrace();
}
}
}
5.如果可能出现多种异常,上面的实例代码很长,代码冗余量大,最好的方式是在一个catch语句块中实现对三个异常的捕获
合并处理方案:一个catch块捕捉多种异常
1.使用 | 符分隔不同的异常类型
try{
System.out.println(12/0);
Object strA = "";
System.out.println((Integer)strA);
fis=new FileInputStream(file);//本try块中有可能出现三种不同的异常
}catch (ArithmeticException|ClassCastException|FileNotFoundException e){
}
2.在catch块中声明父类异常,捕捉所有子类异常
Exception类异常是ArithmeticException,ClassCastException,FileNotFoundException三种异常的父类异常
try{
System.out.println(12/0);
Object strA = "";
System.out.println((Integer)strA);
fis=new FileInputStream(file);//本try块中有可能出现三种不同的异常
}catch (Exception e){
}
补充说明异常的继承树:
6.catch块异常捕捉的顺序:子类异常优先处理,父类异常后置处理
捕捉异常时要查找的子类异常要往前放
try{
List list = new ArrayList<>();
list.remove(8);//IndexoutofBoundsException
int[] arr = new int[2];
arr[8]=22;//ArrayIndexoutofBoundsException
String strA="abc";
strA.charAt(8);//StringIndexoutofBoundsException
}catch (IndexOutOfBoundsException e){
e.printStackTrace();
}//catch (ArrayIndexoutofBoundsException e){} 这里会报错因为A异常是I异常的子类
finally {
System.out.println("999");
}
这里运行完程序后会抛出异常
7.先创建两个测试类test1 test2
public static int test1(){
try {
System.out.println(12/0);
return 1;
}catch (Exception e) {
return 2;
}finally {
return 3;
}
}
public static int test2(){
try {
System.out.println(12/0);
return 1;
}catch (Exception e){
return 2;
}finally {
System.out.println(12/0);
return 3;
}
}
如果catch块抛出了异常,没有finally就会中断程序
无finally时在主函数中调用test1方法,返回值为2
如果catch块抛出了异常,并且有finally,finally会运行并且正常返回
有finally时执行test1,返回值为3
8. try不能单独编写,必须有其他语句块(catch和finally之一或之二)
try块里没有检查性异常时,不能在catch中随意捕捉
public static void test(){
try{
System.out.println(12/0);
//try块里不能出现检查型异常时,才能写出try...finally
}catch (Exception e){
}
}
9.throws throw
throws 声明方法中可能抛出的异常
throw 抛出多种异常
10.自定义异常
先创建一个类Student,在其中定义抛出异常的方法时,方法要跟 throws+异常名称
注意:检查性方法需要声明,声明这个方法会抛出哪个异常
运行时异常可以不在方法名处这样声明
class Student{
String name;
public void info() throws StudentNameIsNullException//检查性方法需要声明,声明这个方法会抛出哪个异常
{
//name==null是一种特殊情况,不符合业务需求,将其当作异常
if (name==null){
throw new StudentNameIsNullException("student name is null");
}
System.out.println("我的名字是"+name);
}
public void infoA() //运行时异常可以不声明
{
if (name==null){
throw new NullPointerException("name is null");
}
}
}
//检查性异常 是Exception的直接子类
class StudentNameIsNullException extends Exception{
public StudentNameIsNullException(){}
public StudentNameIsNullException(String msg){
super(msg);
}
}
方法重写:子类对父类中继承过来的方法进行重新定义
约束条件:返回值类型、方法名、参数列表不能变、访问权限只能更开放不能更小、重写的方法抛出的异常只能更精确(小),不能扩大
class BigStudent extends Student{
@Override
public void info()//子类继承父类时,抛出的异常只能更精确(小),0也可以,但不能更大!!!!!!!!!
{
}
}
11.Java中对文件的处理 File
目前已经见过的包: 已经见过java.lang(默认导入) ,java.util,今天新认识一个java.io包
12.在Java中声明一个文件:
//在java中声明一个文件 传入字符串当作文件的地址
File f =new File("D:\\easy.txt");
判断是否存在该文件:
//是否存在该文件
boolean bool = f.exists();
System.out.println(bool);
创建一个文件:使用createNewFile()方法
因为我电脑中本来是没有这个文件的,所以我对布尔类型的bool进行取反!,使代码能够创建出新的文件
if (!bool){
try {
bool=f.createNewFile();
if (bool){
System.out.println("成功创建文件");
}
}
catch (IOException e){
e.printStackTrace();
}
}
判断是否是该文件:
//获取是否是文件
bool = f.isFile();
System.out.println(bool);
获取的是否是文件夹:
//获取是否是文件夹
bool = f.isDirectory();
System.out.println(bool);
创建文件夹的两种方式:
//创建文件夹
//前面的路径(前面的文件夹)必须都存在
f.mkdir();
//前面的路径没有就直接创造出来
f.mkdirs();
删除文件夹:
注意!!!!:删除文件夹时,文件夹必须是空的,否则将执行不了删除指令
if (!bool){
try {
bool=f.createNewFile();
if (bool){
System.out.println("成功创建文件");
}
}
catch (IOException e){
e.printStackTrace();
}
}else {
//删除文件夹时,文件夹必须是空的
f=new File("");
bool = f.delete();//删除
System.out.println("成功删除文件"+bool);
}
13.IO流
In输入流 Out输出流 流动的是数据(二进制数据)
分类:
根据流动的方向不同 输入流和输出流
根据流动的介质(单位)不同 分为字符流、字节流
注意:字符流只能读取文本.txt.xml.properties.html.yml
字节流什么文件都可以读取 ,只能把字节流转化成字符流
根据功能(作用)不同, 分为节点流(怼在文件上的流)、工具流(更方便地读取) 如打印流 数据流 对象流
14.字节流:
字节输入流 InputStream is;
字节输出流 OutputStream os;
字符流:
字符输入流 Reader r;
字符输出流 Writer w;
15.读取文件:
写一个方法用来读取文件
public static void readFile(){
//读取文件
FileInputStream fis=null;
try{
fis = new FileInputStream("D:\\easy.txt");
byte[] arr=new byte[16];
int length=0;
while ((length=fis.read(arr))!=-1){//这样写避免乱码的产生
//arr中就是读取到的数据
String str=new String(arr,0,length);//1
System.out.println(str);
//String.valueOf(arr);//2种方式将其他类型转化成字符串
}
}catch (IOException e){
e.printStackTrace();
}finally {
if (fis!=null){
try {
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
17.缓冲流
public static void readFileBuffer(){
//缓冲流Buffer
//工具流:转换流、缓冲流
FileInputStream fis=null;//文件字节输入流
BufferedReader br=null;//缓冲流
InputStreamReader isr = null; //转换流
try {
fis = new FileInputStream("D:\\easy.txt");
isr=new InputStreamReader(fis);//字符流套在直接插在缓存中的字节流上
br=new BufferedReader(isr);
String line = br.readLine();//读一行返回字符串
System.out.println(line);
}catch (IOException e){
e.printStackTrace();
}finally {
if (fis!=null){
try {
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
18.将字符串存入文件中
public static void writeFile(){
//将字符存入txt文件中
String str="tsk很帅";
byte[] arr=str.getBytes();
FileOutputStream fos =null;
try{
fos=new FileOutputStream("D:\\easy.txt",true);//追加一个true,这样就不会覆盖之前的内容(默认是覆盖之前内容)
fos.write(arr);
}catch (IOException e){
e.printStackTrace();
}finally {
if (fos!=null){
try {
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
19.将对象存入文件中:
将内存对象转换成序列(流),叫做序列化
这个对象必须是可序列化的(类Staff必须实现Serializable接口)
public static void writeObject(){
Staff staff = new Staff();
staff.name="张三";
staff.sex="男";
staff.salary=8000;
ObjectOutputStream oos = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream("D:\\easy.txt");
oos = new ObjectOutputStream(fos);
oos.writeObject(staff);
}catch (IOException e){
e.printStackTrace();
}finally {
if (oos!=null){
try {
oos.close();
}catch (IOException e){}
}
if (fos!=null){
try {
fos.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
下图为创建的Staff类:
实现了Serializable接口
20.反序列化
将对象序列读入程序,转换成对象的方式:反序列化
反序列化会返回新的对象
类Staff必须实现Serializable接口
public static void readObject(){
FileInputStream fis =null;
ObjectInputStream ois =null;
try {
fis=new FileInputStream("D:\\easy.txt");
ois=new ObjectInputStream(fis);
Object obj = ois.readObject();
System.out.println(obj);
}catch (Exception e){
e.printStackTrace();
}finally {
if (ois!=null){
try {
ois.close();
}catch (IOException e){
e.printStackTrace();
}
}
if (fis!=null){
try {
fis.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
21.小总结:创建对象的方式:
1.new 2.克隆复制一份 3.反序列化