Java面向对象(二)

本文详细介绍了Java中的异常处理机制,包括异常的层次结构、处理方式,以及`throws`和`throw`的区别。此外,还探讨了IO流的基本概念,如字节流和字符流,并提供了相关示例代码。最后,讲解了序列化和反序列化的概念、应用场景以及注意事项,强调了序列化ID的一致性对反序列化成功的重要性。
摘要由CSDN通过智能技术生成

注:本章节用来复习异常、IO流、序列化相关知识。

一、异常

异常是用来封装错误信息的对象;它由异常的类型、提示信息、报错的行号提示三部分组成;

1.异常的体系架构

        第一层:顶级父类Throwable  

        第二层:Error和Exception

                    Error:错误类,表示系统内部错误或者资源耗尽错误,紧靠修复程序本身是不能恢复  执行的。子类有IOError 、AWTError

                    Exception:异常类,表示程序本身出现的错误,编译错误(编译出错或者运行出错)。

2.异常的处理方式

当程序遇到异常,通常有两种处理方式:捕获异常或者向上抛出。

  • 捕获异常

    try{

            需要捕获的代码

    }catch(异常类型 异常名){

            处理方案

    }

  • 抛出方案

        对于不想现在处理或者处理不了的异常可以选择向上抛出-----在方法上设置了抛出管道---throws异常类型

eg:void method1() throws  Exception1,Exception2{}

TIPS:方法上有默认的异常管道:RuntimeException 

3.throws与throw的区别

              throws:用在方法声明处,其后跟着的是异常的名字,表示此方法会抛出异常,需要有本方法的调用者来处理这些异常。

                throw:用在方法内部,其后跟着的是异常对象的名字,表示在此处抛出异常,由方法体内的语句处理。(执行throw一定抛出了异常)

/**本类用于异常的入门案例*/
public class ExceptionDemo {
    public static void main(String[] args) {
       // method1();//调用用来暴露异常的方法
        //method2();//调用异常解决方案1 -- 捕获处理 --自己解决
        //method3();//调用异常解决方案2 -- 向上抛出 --别人解决
        f();
        //f2();
        f3();
        /**1.10/0
         * --报错ArithmeticException
         * 2.10/3.5
         * --报错InputMismatchException--输入不匹配异常
         * */
        /**1.不要害怕BUG,真正的勇士敢于直面自己写的BUG;
         * 2.学会看报错的信息提示,确定自己错误的方向;
         * 3.学会看报错的行号提示,确定自己报错的位置,哪里不对点哪里
         * 注意:源码不会报错,要看的是自己写的代码
         * */

        /**异常抛出的格式:在方法的小括号与大括号之间,写throws 异常类型
         * 如果有多个异常,使用逗号分隔开
         *
         * 如果一个方法抛出了异常,那么谁来调用这个方法,谁就需要处理这个异常
         * 这里处理也有两种方案:捕获解决  或者  继续向上抛出
         *
         * 注意:我们一般会在main()调用方法之前,将这个方法抛出的异常处理掉
         * 而不是将问题抛给main(),因为调用main()的是JVM,而后面的没人解决了,该报错还是报错
         * */
    }
    private static void f3() {
        try{
            f2();
        }catch (Exception e){
            System.out.println("解决方案~");
        }
    }

    //继续向上抛出异常 ---别人解决
    private static void f2()throws Exception {
        System.out.print("请输入第一个要计算的整数:");
        int a = new Scanner(System.in).nextInt();
        System.out.print("请输入要计算的第二个整数:");
        int b = new Scanner(System.in).nextInt();
        System.out.println(a/b);
    }

    private static void f() {
        try{
            method3();
        }catch (Exception e){
            System.out.println("解决方案~");
        }
    }

    private static void method3()throws Exception {
            System.out.print("请输入第一个要计算的整数:");
            int a = new Scanner(System.in).nextInt();
            System.out.print("请输入要计算的第二个整数:");
            int b = new Scanner(System.in).nextInt();
            System.out.println(a/b);
    }
  /* try{
       可能抛出的异常代码
    }catch(异常的类型  异常的名字){
       万一捕获到了预先设定的异常,进行处理的解决方案
    }
    **/
    private static void method2() {
        try{
            System.out.print("请输入第一个要计算的整数:");
            int a = new Scanner(System.in).nextInt();
            System.out.print("请输入要计算的第二个整数:");
            int b = new Scanner(System.in).nextInt();
            System.out.println(a/b);
        }catch (ArithmeticException e){
            System.out.println("除数不能为0");
        }catch (InputMismatchException e){
            System.out.println("请输入规定的整数!");
        /**使用多态的思想,不论是什么子异常,统一看作父类型Exception
         * 做出更加通用的解决方案,甚至可以只写这一个,上面那2个不写了*/
        }catch (Exception e){
            System.out.println("输入的数据不对,请重新输入~~");
        }
    }
    
}

二、IO流

8.1流的分类:

  根据流的传输处理的单位:字节流        字符流

  根据流的方向:输入流        输出流

  • 字节输入流InputStream---抽象父级,无法实例化

    FileInputStream ---操作文件的字节输入流,构造要:File/路径

    BufferdInputStream:高效字节输入流,构造方法要:InputStream

  • 字节输出流OutputStream---抽象父级,无法实例化

    FileOutputStream---操作文件的字节输出流,构造函数有(File)、(File, boolean append)、(String name)、(String name, boolean append)

    注意:这四种都可可以覆盖输出;

    BufferedOutputStream---高效字节输出流,构造要:OutputStream

  • 字符输入流Reader---抽象父级,无法实例化

     FileReader---操作文件的字符输入流,构造要:File/路径

     BufferedReader---高效字符输入流,构造要:Reader

  • 字符输出流Writer---抽象父级,无法实例化

     FileWriter---操作文件的字符输出流,构造有:(File)、(File, boolean append)、(String name)、(String name, boolean append)

    BufferedWriter---高效字符输出流,构造要:Writer

import java.io.*;

/**本类用于测试字节输入流*/
public class TestIn {
    public static void main(String[] args) {
        method();
        method2();
    }
    private static void method2() {
        FileInputStream in = null;
        try {
            in = new FileInputStream("D:\\ready\\1.txt");
        int b;
        while ((b = in.read()) != -1){
            System.out.println(b);
        }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void method() {
        //InputStream in = new InputStream();--抽象父级不可以被实例化
        FileInputStream in = null;
        try {
           in = new FileInputStream(new File("D:\\ready\\1.txt"));

//            System.out.println(in.read());//97
//            System.out.println(in.read());//98
//            System.out.println(in.read());//99
//            System.out.println(in.read());//-1
            //需求:需要循环读取文件中的所有内容,直至读完
            //定义变量,保存读取到的数据
            int b;
            while (( b = in.read()) != -1){//只要读到的数据不为-1,说明还有数据
                System.out.println(b);//就打印当前循环读到的数据
            }
            //关流
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        /**finally{}代码块是try-catch结果中的第三个部分
         * 这个部分,不论是否扑捉到了异常,最终都会执行
         * 也就是说,这是一块一定会被执行的代码块,常用于关流操作*/
        }finally {
            //关流---流对象使用完必须释放!
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
/*********************************************************************/
import java.io.*;

/**本类用于测试字节输出流*/
public class TestOut {
    public static void main(String[] args) {
     //   method1();//用于测试普通字节输出流
        method2();//用于测试高效字节输出流
    }

    private static void method2() {
        BufferedOutputStream out = null;
        try {
          //  out = new BufferedOutputStream(new FileOutputStream("D:\\ready\\1.txt"));
            out = new BufferedOutputStream(
                    new FileOutputStream(new File("D:\\ready\\1.txt"),true));
            out.write(99);
            out.write(99);
            out.write(99);
        }catch (Exception e){
                e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private static void method1() {
        FileOutputStream out = null;
        try {
           // out = new FileOutputStream(new File("D:\\ready\\1.txt"));
          out  = new FileOutputStream("D:\\ready\\1.txt",true);
        out.write(97);
        out.write(98);
        out.write(99);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
/**本类用于测试字符输入流*/
public class TestIn2 {
    public static void main(String[] args) {
       method1();//普通输入流读取
       method2();//高效输入流读取
    }
    private static void method2() {
        BufferedReader in1 = null;
        try {
            in1 = new BufferedReader(
                    new FileReader("D:\\ready\\1.txt"));
        int b;
        while((b = in1.read())!= -1){
            System.out.println(b);
        }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                in1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private static void method1() {
        FileReader in = null;
        try {
            //FileReader in2 = new FileReader(new File("D:\\ready\\1.txt"));
        in = new FileReader("D:\\ready\\1.txt");

        int b;
        while((b = in.read())!= -1){
            System.out.println(b);
        }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
/*******************************************************************/
/**本类用于测试字符输出流*/
public class TestOut2 {
    public static void main(String[] args) {
        //method1();//用于测试普通字符输出流
        method2();//用于测试高效字符输出流
    }

    private static void method2() {
        BufferedWriter out2 = null;

            try {
               // out2 = new BufferedWriter(new FileWriter("D:\\ready\\1.txt"));
                out2 = new BufferedWriter(new FileWriter(new File(
                        "D:\\ready\\1.txt"),true));
             //   out2 = new BufferedWriter(new FileWriter("D:\\ready\\1.txt",true));
                out2.write(98);
                out2.write(98);
                out2.write(98);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    out2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }

    private static void method1() {
        FileWriter in = null;
        try{
          in = new FileWriter("D:\\ready\\1.txt");
            in.write(97);
          in.write(97);
          in.write(97);
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

三、序列化与反序列化

1.概述

序列化:把对象的信息保存到文件中---ObjectOutputStream

    反序列化:ObjectInputStream对以前使用的 ObjectOutputStream写入的基本书记和对象进行反序列化重构对象。

  • 准备Student类,注意:需要实现可序列化的接口
  • 创建序列化流对象;
  • 创建被序列化输出的学生类对象;
  • 用流对象

注意:自定义类需要重写toString()才能查看对象的属性与属性值,否则打印地址值。

反序列化如何成功?

        核心:Student类中的UID,与反序列化流中的UID保持一致。

  • 一次序列化对应一次序列化;【推荐】
  • 一次序列化后不修改Student中的内容,然后反序列化;
  • 将Student中的UID写成固定值;

注意:反序列化流持有UID与Student类中的UID不一致时,反序列化会失败---eg:使用自动生成的UID,先序列化,然后修改Student,再来反序列化,这样就会失败。

2序列化的应用场景

  • 需要序列化的文件必须实现Serializable接口,用来启动序列化功能;
  • 不需要序列化的数据可以修饰成static,原因:static资源属于类资源,不随着对象被序列化输出;
  • 每一个被序列化的文件都有唯一的id,如果没有添加此id,编译器会自动根据类的定义信息计算产生一个;
  • 在反序列化时,如果和序列化的版本号不一致,无法完成反序列化;
  • 常用与服务器之间的数据传输,序列化成文件、反序列化读取数据;
  • 常用使用套接字流在主机之间传递对象;
  • 不需要序列化的数据可以被修饰成transient(临时),只在程序运行期间在内存中存在,不会被序列化持久保存。
import java.io.*;

/**本类用于测试序列化与反序列化
 * 序列化:
 * 是指把程序中的Java对象,永久保存在磁盘中,
 * 相当于是写出的过程,方向是out,对应的流是:ObjectOutputStream
 * 反序列化:
 * 是指把已经序列化在文件中保存的数据,读取/恢复到Java程序中的过程
 * 方向是in,对应流是:ObjectInputStream
 *
 * */
public class TestSerializeable {
    public static void main(String[] args) {
        method1();//完成序列化
        method2();//完成反序列化
    }

    private static void method2() {
        ObjectInputStream in = null;
        try{
            in = new ObjectInputStream(
                    new FileInputStream("D:\\ready\\1.txt"));
            System.out.println(in.readObject());
            System.out.println("反序列化成功~~~");
        }catch(Exception e){
            System.out.println("反序列化失败~~~");
            e.printStackTrace();
        }finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**序列化方法*/
    private static void method1() {
        //1.声明一个在本方法中生效的局部变量,局部变量不需要初始化
        ObjectOutputStream out =null;
        //2.由于IO操作可能会抛出异常,所以需要完成try-catch结构
        try{
            //创建流对象
            out = new ObjectOutputStream(
                    new FileOutputStream("D:\\ready\\1.txt"));
            //指定要序列化的对象
            Student obj = new Student("海绵宝宝",3,"海里",'男');
            out.writeObject(obj);
            System.out.println("序列化成功~");
        }catch (Exception e){
            System.out.println("序列化失败~~");
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值