Java-02 面向对象5

本文详细介绍了Java中的IO流分类、核心流、File类的功能以及序列化与反序列化原理,重点讲解了字节流、字符流、FileInputStream/FileOutputStream和ObjectInputStream/ObjectOutputStream的应用。
摘要由CSDN通过智能技术生成

1. IO流

        1)概述:I 即 Input/read;O 即 Output/write。IO流主要是用于实现数据(文件)的读写(以二进制的形式)。

        2)分类:

                · 按照流的方向(以内存为参照物)

                        往内存中去的称为Input(Read);

                        从内存中出来称为Output(Write);

                · 按照一次提取的是字符/字节:

                        一次读取一个字节的称为字节流;

                        一次读取一个字符的称为字符流;

        3)Java中的IO流:

                Java中的所有IO流都已经写好,并存放在java.io.*下。

                四大IO流(父类)

                        · java.io.InputStream              // 字节输入流

                        · java.io.OutputStraem            // 字节输出流

                        · java.io.Reader                  // 字符输入流

                        · java.io.Writer                   // 字符输出流

 注意:

        1)在Java中以Stream结尾的都是字节流,以上的四大IO流都是抽象类;                                2)所有的流都实现了 java.io.Closable 接口,都是可关闭的(重写了close()方法);由于流是一个介于内存和硬盘之间的管道,用完之后一定要关闭,否则会耗费很多资源。

        3)所有的输出流(OutputStream/Writer)都实现了java.io.flushable 接口,都是可刷新的(重写了flush()方法);一个比较好的习惯是,在输出流最终输出之后,通过调用flush()方法刷新一下,这个刷新表示将管道中未输出的数据强行输出完(即清空管道),不刷新可能导致数据丢失。

                比较重要的流:

                        文件专属流:

                                java.io.FileInputStream

                                java.io.FileOutputStream

                                java.io.FileReader

                                java.io.FileWriter

                        对象专属流:

                                java.io.ObjectInputStream

                                java.io.ObjectOutputStream

注意:

        1)FileInputStream/FileOutputStream是字节流、实体流,一般用来处理二进制文件,通过path(路径)的方式指定目录/文件(数据源);

        2)ObjectInputStream/ObjectInputStream是装饰流,装饰流不能直接处理数据源,而是需要与其他的装饰流/实体流一起使用,例如ObjectInputStream对象就常用FileOutputStream对象作为构造方法的输入参数。ObjectInputStream/ObjectInputStream最重要的功能是通过序列化与反序列化实现数据的持久化。

              

2. File类 

           1) 概述:

                File类的父类是Object类,File类不能完成文件的读和写;

                File类对象代表的是文件和目录的抽象表示形式(路径),一个File对象既可以是目录,也可以是文件。

例如:

        C:\Drivers    即为一个File对象(目录)

        C:\Drivers\Lan\Realtek\Readme.txt    也是一个File对象(文件)

                2)File的常用方法:

                        · 构造方法 File(String PathName)

                        · boolean exists()          // 判断File对象是否存在

                        · boolean createNewFile()  // 将File对象以文件的形式创建出来

                        · boolean mkdir()   // 将File对象以目录的形式创建出来

                        · String getName()    // 获取File对象的文件名

                        · boolean isDirectory()     // 判断File对象是不是目录

                        · boolean isFile()     // 判断File对象是不是文件

                        · String getAbsolutePath()  // 获取File对象的绝对路径

                        · File[] listFiles()            // 获取当前目录下所有的子文件

3. 序列化与反序列化

        1)什么是序列化与反序列化:

               序列化(Serialize)就是将一对象及其状态转换为字节序列(二进制),保存起来(可以保存在数据库,内存,文件等),ObjectOutputStream负责序列化,然后可以在适当的时候再将其状态恢复(也就是反序列化,Deserialize),ObjectInputStream负责反序列化。     

        2)为什么要进行序列化:

                · 持久化:在Java中对象是保持在“堆”中的,堆是一个内存空间,不能长期保持,程序关闭对象就会被回收。但是有时候,我们是需要保存对象里面的信息的,这个时候就需要对对象进行持久化,对象序列化其实就是持久化。

                · 微服务:各个服务之间调用对象就需要把对象序列化用于在网络上传输。

                · 传输:Java 对象本质上是class 字节码,很多机器都不能根据这个字节码识别出该 Java 对象。但是序列化是序列成二进制流,二进制在计算机世界是通用的。

        3)涉及的API:

                · java.io.ObjectOutputStream(对象输出流),它的writeObject(Object obj)方法可以对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

                 · java.io.ObjectInputStream(对象输入流),它的readObject()方法源输入流中读取字节序列,再把它们反序列化成为一个对象,并将其返回。

        4)序列化的步骤:

                · 序列化:

// 序列化一个Person对象
public static void main(String[] args) throws IOException {
    //创建java对象(java对象必须支持Serializable接口才可以序列化)
    Person p = new Person("Tony",25,'M');
    //序列化
    //在当前路径下创建一个名为name的文件并传入对象
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("preson1"));
			
    //序列化对象
    oos.writeObject(p);
			
    //刷新
    oos.flush();
    //关闭
    oos.close();
}

                · 反序列化:

// 反序列化Person对象
public static void main(String[] args) throws IOException, ClassNotFoundException {
    // 创建反序列化流
	ObjectInputStream ois = new ObjectInputStream(new FileInputStream("preson1"));
			
    // 开始反序列化
    // readObject() 以Object对象的形式返回流中的对象
    Object obj = ois.readObject();

	// 反序列化回来以后是一个Preson对象,会调用Person对象的toString方法
    System.out.println(obj);

    // 关闭
    ois.close();
}

        5)可序列化接口 Serializable
        只有当一个类实现了 Serializable 接口时,这个类的实例才是可序列化的。Serializable 接口是一个标识接口,用于标识一个对象是否可被序列化,该接口不包含任何数据域和方法。但是Serializable接口起到了标识的作用,java虚拟接看到这个类实现了该接口之后,会自动生成一个序列化版本号。

        如果试图对一个没有实现 Serializable 接口的类的实例进行序列化,会抛出 NotSerializableException 异常。

        特点:如果某个类能够被序列化,其子类也可以被序列化。声明为static和transient类型的成员数据(transient关键字只能修饰数据域,不能修饰类/方法)不能被序列化。因为static代表类的状态, transient代表对象的临时数据(可以用transient声明不需要被序列化的数据域)。

        如果一个对象的类实现了 Serializable 接口,但是包含一个不可序列化的数据域,则该对象不可序列化。为了使该对象可序列化,需要给不可序列化的数据域加上关键字 transient。

        6)serialVersionUID:

                作用:java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地实体类中的serialVersionUID进行比较,如果相同则认为是一致的,便可以进行反序列化,否则就会报序列化版本不一致的异常。

                生成方法

                        · JVM编译时默认生成:根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段;

                        · 手动设置:手动在代码中设置serialVersionUID,比如:private static final long serialVersionUID = 1L;

                核心功能:保证版本兼容性,当类的实例Serialized存到硬盘上面后,可是后来你却更改了该类的数据域field(增加或减少或改名),将硬盘上的数据Deserialize时,就会出现Exception的,这样就会造成不兼容性的问题。但当serialVersionUID相同时,它就会将不一样的field以type的预设值Deserialize,可避开不兼容性问题。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值