IO流

概述

IO流,又叫输入输出流,当我们将内存中的数据写到硬盘上时,这个过程叫输出流(Output),当我们将硬盘上的数据读取到内存中时,叫做输入流(Input)。流本身是一个抽象概念,是 对数据传输的总称,也就是说,数据在设备键的传输,叫做流

重点:

明确操作是读还是写

使用何种类型的流

铺垫技术:

学习IO流之前,我们需要学习两个铺垫技术:一个是异常,一个是File类

**异常:**因为在介质传输数据会有很多问题,比如:找不到文件,文件格式错误,读写错误,我们需要知道当进入到这些问题时,如何去处理

**File:**流的操作会涉及很多的文件操作,所以我们也要学习与文件相关的类—File类

异常:

**概述:**程序出现 不正常的情况

分类:

程序异常:Throwable Throwable 类是 Java 语言中所有错误或异常的父类

严重问题----Error:我们不去处理,因为处理不了,比如:内存溢出问题

一般问题----Exception:

编译时异常:除了RuntimeException的异常都是编译时异常,这种异常必须在程序执行前进行处理。

运行时异常:RuntimeException,这个问题我们也不做处理。因为造成的原因多数是我们的逻辑不够严谨,需要我们去修改代码
案例:

public class ExceptionDemo {
    public static void main(String[] args) {
        //第一模块
        int a = 10;
        int b = 0;
        System.out.println(a / b);

        System.out.println("我是第二模块");
    }
}

分析:

程序出现问题后,控制台打印错误信息:包括Exception包名+类名,错误的描述,错误出现的位置。这些对于异常的操作我们并没有做,而是JVM替我们做的。

所以,当我们不做任何异常处理时,我们的JVM会对异常执行一个默认的操作

异常处理:
方式:

try…catch…finally

throws

try…catch…finally

格式:

try{
    //可能出现问题的代码
}catch(异常类名 变量名){
    
    //针对异常的处理
    
    
    
}finally{
    
    //释放资源
    //它不是必须
    
}

**注意:

1.try里面包裹的代码越少越好,因为被try包裹的代码在执行时需要走异常处理机制,需要JVM给该机制分配额外的资源去管理代码,所以包裹越少,越节省资源

2.catch中必须有对异常的处理,哪怕时一句输出语句也可以,因为不做任何处理的话,相当于把异常隐藏了,而不是处理了

3.try结构中的语句,一但捕获到异常,剩下的代码不再执行,直接执行catch的代码

示例:

/**
 * 多个异常的处理
 */
public class ExceptionDemo2 {
    public static void main(String[] args) {
        method();
        System.out.println("程序执行完毕");
    }

    private static void method() {
        int a = 10;
        int b = 0;
        try {
           //System.out.println(a / b);
            int[] c = {1, 2, 3};
            System.out.println(c[4]);
        } catch (ArithmeticException arithmeticException) {
            System.out.println("除数不能为0");
           // arithmeticException.printStackTrace();
        } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) {
            System.out.println("数组越界了" );
        }


    }
}
/**
 * 多个异常的处理
 */
public class ExceptionA {
    public static void main(String[] args) {
        method();
        System.out.println("程序执行完毕");

    }
     //多个try...catch
    public static void method() {
        int a = 10;
        int b = 0;
        try {
            System.out.println(a / b);

        } catch (ArithmeticException arithmeticException) {
            System.out.println("除数不能为0!");

        }

        try {
            int[] c = {1, 2, 3};
            System.out.println(c[4]);

        } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) {
            System.out.println("出错了");
        }
    }
}

处理方式:

1.一个try,多个catch

a.如果异常类在继承体系结构中处于平级关系,他们呢的前后不影响执行结果

b.如果异常在继承体系结构中处于父子关系,则父类异常必须写在后面,否则子类异常不会被正常匹配到

2.多个try…catch

3.一个try…catch,catch中的类可以写Exception类,它可以用来匹配所有子类异常

JDK7新特性–异常处理

格式:

try{
    //可能出现异常的代码
}catch(异常1 |异常2|...变量名){
    //异常处理
}
public class ExceptionDemo3 {
    public static void main(String[] args) {
         method();
        System.out.println("程序结束");
    }

    private static void method() {
        int a = 10;
        int b = 0;
        int[] c = {1, 2, 3};
        try {
            System.out.println(a / b);
            System.out.println(c[4]);

        } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
            System.out.println("出错了");
        }

    }
}

注意:

1.多个异常必须是平级关系

2.针对不同异常,处理方式一致

编译时异常和运行时异常

**编译时异常:**我们在执行程序,必须处理掉的异常,如果不处理,程序将不能编译正常

**运行时异常:**不需要我们显示处理,但是我们也可以使用try…catch处理

案例:

/**
 * 编译时异常:必须通过异常处理,代码才能通过编译
 */
public class ExceptionDemo4 {
    public static void main(String[] args) {
        String day = "2020-11-29";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd");
        try {
            Date date = sdf.parse(day);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
Throwable

常用方法:

/**
 * Throwable:
 * public String getMessage():返回此 throwable 的详细消息字符串。
 * public String toString():返回此 throwable 的简短描述。
 *     组成:
 *        此异常类的全路径类名
 *        ":"
 *         调用此对象 getLocalizedMessage() 方法的结果 
 *           如果 getLocalizedMessage 返回 null,则只返回类名称。 
 * public void printStackTrace():获取异常类名和异常信息描述以及错误出现的位置
 * public void printStackTrace(PrintStream s):将此 throwable 及其追踪输出到指定的输出流。
 */
throws

在开发中,如果去调用别人写的代码,我们很难判断调用方法时是否会发生异常。针对这种情况,java允许在方法后面使用throws关键字对外声明该方法在使用过程中可能发生的异常,这样调用者在调用方法时,就明确知道该方法有异常,并必须处理掉异常,否则代码将无法通过编译。

格式

方法()throws 异常类名1,异常类名2,...

注意:

我们在调用方法时,如果不做异常处理,我们可以选择抛出(throws),直到main方法抛给JVM为止,这种情况,JVM就会采取默认处理方式处理异常,尽量不要在主方法抛出。

案例:

/**
 * throws 演示案例
 */
public class ThrowsDemo {
    public static void main(String[] args)  {
       // method();
        try {
            method2();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println("程序结束");
    }

//    private static void method()throws ArithmeticException {
//        int a = 10;
//        int b = 0;
//        System.out.println(a / b);
//    }

    private static void method2() throws ParseException {
        String day = "2020-11-29";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd");
        Date date = sdf.parse(day);
    }
}

根据演示案例,我们知道

编译时异常抛出:调用者必须处理

运行时异常抛出:调用者可以不处理

throws 和 throw

案例

/**
 * throws 演示案例
 */
public class ThrowsDemo {
    public static void main(String[] args)  {
       // method();
        method3();
//        try {
//            method2();
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
        System.out.println("程序结束");
    }

//    private static void method()throws ArithmeticException {
//        int a = 10;
//        int b = 0;
//        System.out.println(a / b);
//    }

    private static void method2() throws ParseException {
        String day = "2020-11-29";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM--dd");
        Date date = sdf.parse(day);
    }

    private static void method3()throws ArithmeticException {
       int a = 10;
        int b = 1;
        if (b == 0) {
            throw new ArithmeticException();
        } else {
            System.out.println(a / b);
        }

   }
}

总结:

throw:

1.方法体内,后面跟异常对象

2.只能抛一个异常

3.执行throw,表示一定有异常抛出

throws:

1.方法声明上,后面跟异常类名

2.可以抛多个异常,用,隔开

3.throws,表示可能有异常抛出

finally

概述:

被finally包裹的代码一定会被执行,但是,JVM退出

面试题

1.final,finally,finalize的区别?

final:它表示最终的,可以 类,成员变量,成员方法

类:表示最终类,不能被继承

成员变量:常量,不能被赋值

成员方法:最终方法,不能被重写

finally:它是 异常处理中try…catch…finally结构的一部分,这部分代码最终都会被执行,除了JVM退出。它一般用于释放资源

自定义异常:

注意事项:

1.自定义异常类必须继承Exception或RUntimeException

2.在其有参构造中,一定要指定访问父类的有参构造,这样才能把异常信息打印到控制台上

异常注意事项:

1.子类在重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类异常

2.如果父类抛出多个异常,子类重写父类方法时,只能抛出相同的异常或父类异常的子集,并且子类不能抛出父类中没有抛出的异常

3.如果被重写的方法没有抛出编译时异常,那么子类绝对不能抛出任何编译时异常,如果重写方法中有异常需要处理,只能选择try-catch,不能throws