IO流,对象序列化

对象序列化

 序列化机制允许将实现序列化的Java对象转换成字节序列,这些字节序列可以保存在磁盘上,或者用于网络传输,以备以后重新恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。

 对象的序列化(Serialize)指将一个Java对象写入IO流中,与此对应的是,对象的反序列化(Deserialize)则是指从IO流中恢复该Java对象。如要让某个对象支持序列化机制,则必须要让它的类是可序列化的(Serializable)。为了让某个类是可序列化的,该类需要继承如下两个接口之一:

  1. Serializable接口

  2. Externliazble接口

我们先从Serializable接口开始说起。当类继承了Serializable接口时,该类是可序列化的,即创建出来的对象,可以写入磁盘或者用于网络传输(基本上用于网络传输的类都是序列化的,否则程序会出现异常。若有接触过Java web开发的同学,在web应用中的HttpSession 或ServletContext就是可序列化的类)。

我们如何操作输入/输出可序列化的对象呢,答案是使用ObjectInputStream与ObjectOutputStream的字节流进行操作,这两个流不仅仅是字节流还是处理流,因此需要一个任意节点流作为基础。

下面实现将可序列化对象写入文件,并从该文件读取该对象,并打印该对象的私有属性值

//可序列化 类

class Person implements Serializable{
    String name;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法:我叫"+name+",我今年"+age+"岁了!");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
//实现可序列化对象的传输public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            Person p = (Person)ois.readObject();
            System.out.println("对象序列化,我叫"+p.getName()+",我今年"+p.getAge()+"岁了!");
            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));
            Person p = new Person("HJL",23);
            oos.writeObject(p);
            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

上述代码中,我们先创建了p对象,并将这个p对象写入到当前程序目录下的out.txt文件里,在从该文件中取出对象,并打印该对象的属性值。运行效果如下:

构造方法:我叫HJL,我今年23岁了!
对象序列化,我叫HJL,我今年23岁了!

out.txt文件内容如下:

?? sr File.Person??,H:2{: I ageL namet Ljava/lang/String;xp   t HJL

这里要提醒一点,不是所有的输入流,对磁盘或者网络能写入对象,便可以实现对象的序列化,不如说通过重定向标准输入流,对System.out原先是输出到控制台(显示器)变成输出到指定文件,这样是可以将对象写入到文件中,不过文件中存储的只是当前程序使用该对象时的引用地址,当程序关闭时,该地址时不存在的,因此实现对象序列化的两个步骤,1时让类继承Serializable或者Extemalizable接口并创建对象,第二,通过ObjectInputStream或者ObjectOutputStream操作可序列化的对象。

对象引用的序列化:

 在之前的代码中,我们可以看到的继承Serializable接口的属性都是基本数据类型。若是该类中有引用数据类型时,为了保证该类的实例能正常的序列化与反序列化,该类的引用数据类型对应的类也需要继承Serializable或者Extemaliazble接口。

如下代码:

class Teacher implements Serializable{
    Person student;
    String name;

    public Teacher(String name,Person student){
        this.student = student;
        this.name = name;
    }

    public Person getStudent() {
        return student;
    }

    public void setStudent(Person student) {
        this.student = student;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            Teacher t1 = (Teacher)ois.readObject();
            Teacher t2 = (Teacher)ois.readObject();
            Person p = (Person)ois.readObject();
            Teacher t3 = (Teacher)ois.readObject();
            System.out.println(t1);
            System.out.println(t2);
            System.out.println(t3);
            System.out.println(p);
            System.out.println(t1.getStudent() == p);
            System.out.println(t2.getStudent() == p);

            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));
            Person p = new Person("HJL",23);
            Teacher t1 = new Teacher("PP",p);
            Teacher t2 = new Teacher("CC",p);
            oos.writeObject(t1);
            oos.writeObject(t2);
            oos.writeObject(p);
            oos.writeObject(t2);

            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

其运行结果为:

构造方法:我叫HJL,我今年23岁了!
[email protected]
[email protected]
[email protected]
[email protected]
true
true

是所以会产生这样的运行结果,是因为在java序列机制中采用了一种特殊的序列化算法,其算法内容如下:

 1. 所有保存到磁盘中的对象都有一个序列化编号。

 2. 当程序试图序列化一个对象时,程序会先检查该对象是否已经被序列化过,只有该对象从未(本次虚拟机中)被序列化过,系统才会将该对象转换成字节序列并输出。

 3. 若该对象已经序列化过了,程序将知识直接输出一个序列化编号,而不是再次重新序列化该对象。

因此在上述代码中,当从文件中取出对象时,先是序列化了p对象,再是序列化t1对象,然后序列化t2对象时,发现p对象已经序列化过了,返回序p的列化编号,第三序列化p对象时,也发现被序列化过了,因此返回p的序列化编号,最后,序列化t2对象时,发现t2对象也被序列化过了,因此也返回t2的序列化编号。PS,写入/读取对象都是按顺序来的。

public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            Teacher t1 = (Teacher)ois.readObject();
            Teacher t2 = (Teacher)ois.readObject();
            Person p = (Person)ois.readObject();
            Teacher t3 = (Teacher)ois.readObject();
            System.out.println(t1);
            System.out.println(t1.getStudent().getName());
            System.out.println(t2);
            System.out.println(t2.getStudent().getName());
            System.out.println(t3);
            System.out.println(p);
            System.out.println(t1.getStudent() == p);
            System.out.println(t2.getStudent() == p);

            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));
            Person p = new Person("HJL",23);
            Teacher t1 = new Teacher("PP",p);
            System.out.println("read: t1.student.name"+t1.getStudent().getName());
            oos.writeObject(t1);
            p.setName("HJJ");
            Teacher t2 = new Teacher("CC",p);
            System.out.println("read: t2.student.name"+t2.getStudent().getName());
            oos.writeObject(t2);
            oos.writeObject(p);
            oos.writeObject(t2);

            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

运行效果如下:

构造方法:我叫HJL,我今年23岁了!
read: t1.student.nameHJL
read: t2.student.nameHJJ
[email protected]
HJL
[email protected]
HJL
[email protected]
[email protected]
true
true

程序中第一段粗体字代码先使用writeObject()方法写入了一个Person对象,接着程序改变了Person对象的name实例变量值,然后程序再次输出Person对象,但这次的输出已经不会将对象转换成字节序列并输出了,而是仅仅输出了一个序列化编号。

程序中两次调用readObject()方法读取了序列化文件中的Java对象,比较两次读取的Java对象将完全相同,程序输出第二次读取的Person对象的name实例变量的值依然是“HJL”,表明改变后的Person对象并没有被写入----这与Java序列化机制相符。

自定义序列化:

在一些特殊的场景下,如果一个类里包含的某些实例变量是敏感信息,例如银行账户信息等等,这时不希望系统将该实例变量值进行序列化:或者某个实例变量的类型时不可序列的,因此不希望对该实例变量进行递归序列化,以避免引发java.io.NotSetializableException异常。

当对某个对象进行序列化时,系统会自动把该对象的所有实例变量一次进行序列化,如果某个实例变量引用到另一个对象,则被引用的对象也会被序列化;如果被引用的对象的实例变量也引用了其他对象,则被引用的对象也会被序列化,这种情况被称为递归序列化。

通过在实例变量前面使用transient关键字修饰,可以指定Java序列化时无须理会该实例变量。如下Person类与前面的Person类几乎完全一样,只是它的age使用了transint关键子修饰。

修改的Person类:

class Person implements Serializable{
    String name;
    transient int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法:我叫"+name+",我今年"+age+"岁了!");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            Person p = (Person)ois.readObject();
            System.out.println(p.getAge());

            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));
            Person p = new Person("HJL",23);
            oos.writeObject(p);

            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

运行结果如下:

构造方法:我叫HJL,我今年23岁了!
0

由于我们使用了transient关键字修饰了类的成员变量,因此,该成员变量理论上是不被序列化以及反序列化,实际上是该变量以空值的形式进行序列化与反序列化,而int类型的空值是为0。因此上述代码中,从文件取出了对象,并在控制台打印对象的age变量,该变量的为0。

尽管transient关键字修饰实例变量虽然简单,方便,但被transient修饰的实例变量将被完全隔离在序列化机制之外,这样导致在反序列化恢复Java对象时,无法取得该实例变量值。Java还提供了一种自定义序列化机制,通过这种自定义序列化机制可以让程序控制如何序列化各实例变量,甚至完全不序列化某些实例变量(与使用transient关键字的效果相同),而这种自定义序列化机制,是在要实现序列化以及反序列化的类中,通过重写ObjectInputStream的readObject()方法与ObjectOutputStream的writeObject()方法。

一般在默认的情况下,writeObject()方法会调用out.defaultWriteObject来保存Java对象的各实例变量,从而可以实现序列化Java对象状态的目的,而readObject()方法会调用in.defalutWriteObject来反序列化该对象。

除这两种之外,还有另外一种方法,readObjectNoData(),当对方收到的java版本与我发送的java版本不一致的时候,或者因为传输过程中,该反序列化流变得不完整,系统会使用该方法,实现反序列化对象,不过该对象是初始化的状态。

下面我们通过修改上述的person类来实现:

class Person implements Serializable{
    String name;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法:我叫"+name+",我今年"+age+"岁了!");
    }

    private void writeObject(java.io.ObjectOutputStream out) throws IOException{
        // TODO Auto-generated method stub
        //将name实例变量值反转后写入二进制流中
        out.writeObject(new StringBuffer(name).reverse());
//        out.writeInt(age);
    }

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{
        // TODO Auto-generated method stub
        this.name = ((StringBuffer)in.readObject()).reverse().toString();
//        this.age = in.readInt();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            Person t = (Person)ois.readObject();
            System.out.println(t.getAge());

            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));
            Person p = new Person("HJL",23);
            oos.writeObject(p);

            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){     IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

运行结果如下:

构造方法:我叫HJL,我今年23岁了!
0

writeReplace()方法:这是自定义序列化的实现方法之一,比上述的writeObject更彻底,甚至可以在序列化对象时将该对象其换成其他对象。

同样是person类,但这是重写的是writeReplace();

class Person implements Serializable{
    String name;
//    transient int age;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法:我叫"+name+",我今年"+age+"岁了!");
    }

    private Object writeReplace(){
        ArrayList<Object> list = new ArrayList<Object>();
        list.add(name);
        list.add(age);
        return list;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

在上述代码中,我们重写了writeReplace()的方法,在方法中创建了一个list,对list添加数据以及返回list。然后我们继续对这个类的实例写入文件中,并读取文件中该实例数据,并打印该实例数据的类型:

public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            //打印从文件获取对象的类型
            System.out.println(ois.readObject().getClass().getTypeName());

            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));
            Person p = new Person("HJL",23);
            Teacher t = new Teacher("CC", p);
            oos.writeObject(p);

            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

运行效果如下:

构造方法:我叫HJL,我今年23岁了!
java.util.ArrayList

我们可以看到,虽然我们是写入了person类的p对象到out.txt文件中,但中out.txt文件中取出来的对象类型确实list数据类型的。这是因为在Person类中有writeReplace()方法,当要将该类的实例进行序列化前,先会调用writeReplace()方法,并取得该方法的返回值,将该方法的返回值进行序列化后通过对象流存入到了out.txt文件中,所以我们从out.txt文件取对象时,该对象是list类的实例而不是person类的实例。

与上述方法相对应的就是readResolve方法,该方法是作用是当类的实例进行反序列化后,会调用readResolve方法,并获取该方法的返回值,且该返回值会代替原来反序列化的对象:

class Person implements Serializable{
    String name;
//    transient int age;
    int age;

    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法:我叫"+name+",我今年"+age+"岁了!");
    }
    private Object readResolve(){
        Teacher t = new Teacher("CC",this);
        return t;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

我们继续对person类进行修改,添加了readResolve()的方法。IO类保持不变,运行后效果如下:

构造方法:我叫HJL,我今年23岁了!
File.Teacher

值得注意的是,writeReplace()方法与readResolve()方法,是可以使用任意的访问控制符的,如果该类有父类,并且父类实现了writeReplace()方法或者readResolve()方法,并且子类没有重写该方法,将会使得子类序列化或者反序列化的时候执行父类的writeReplace()方法或者readResolve()方法,这明显是程序要的结果,而且开发人员也很难发现错误。但总是让子类重写writeReplace()方法或这readResolve方法无疑是一种负担,因此建议是用final来进行修饰,或者使用peivate进行修饰。

Externalizable接口

在介绍如何实现序列化时,提到了两种实现方法,其一是继承Serializable接口,其二是继承Externalizable接口。若类继承了Externalizable接口,该类要实现如下的两个方法:

  1. readExternal(ObjectInput in):

  2. writeExternal(ObjectOutput out):

上述两个方法与类实现自定义序列化时的readObject()与writeObject()方法很类似,都是用于实现自定义序列化,只是一个使用的是Serializable接口,一个是使用Externalizable接口。

下面我们修改person类,接口Externalizable接口,并重写上述两个方法实现,使用Externalizable接口实现自定义序列化:

class Person implements Externalizable{
    String name;
    int age;

    public Person(){}

    public Person(String name,int age){
        this.name = name;
        this.age = age;
        System.out.println("构造方法:我叫"+name+",我今年"+age+"岁了!");
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        // TODO Auto-generated method stub
        this.name = ((StringBuffer)in.readObject()).reverse().toString();
//        this.age = in.readInt();
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        // TODO Auto-generated method stub
        out.writeObject(new StringBuffer(name).reverse());
//        out.writeInt(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

这里要注意的是,使用Externalizable接口实现对象序列化,但反序列化时,先是根据类的无参构造方法来创建实例,然后才执行readExternal()方法,因此实现Externalizable的序列化类必须提供public的无参构造方法

IO类如下:

public class IO {
    public void readObject(){
        try{
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.txt"));
            Person p = (Person)ois.readObject();
            System.out.println("对象序列化,我叫"+p.getName()+",我今年"+p.getAge()+"岁了!");

            ois.close();
        }catch(Exception e){}
    }
    public void writeObject(){
        try{
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("out.txt"));

            Person p = new Person("HJL",23);
            Teacher t = new Teacher("CC", p);
            oos.writeObject(p);

            oos.close();
        }catch(Exception e){e.printStackTrace();}
    }

    public static void main(String[] args){
        IO io = new IO();
        io.writeObject();
        io.readObject();
    }
}

运行结果如下:

构造方法:我叫HJL,我今年23岁了!
对象序列化,我叫HJL,我今年0岁了!

由于writeExternal()方法只对name成员变量进行序列化以及readExternal()方法也只反序列化name成员变量,因此age成员变量从out.txt文件取出来后值为0。

关于对象序列化,还有以下几点需要注意的:

1.对象的类名,实例变量(包括基本类型,数组,对其他对象的引用)都会被序列化;方法,类变量(被static修饰的成员变量),transient实例的成员变量(也称瞬态实例变量)都不会被序列化

2. 保证序列化对象的实例变量类型也是可序列化的,否则需要使用transient关键字来修饰该实例

3.反序列化对象时必须有序列化对象的class文件

4.当通过文件,网络来读取序列化后的对象时,必须按实际写入的顺序读取,不可乱读。

版本问题:

我们开发java时,都会被开发的java类来制定版本,以便于我们管理。但反序列化Java对象时必须提供该对象的class文件,假如说,我使用person类创建实例,并写入了文件中,过了一会,我修改了person类的成员变量(可以是添加成员变量,可以是删除成员变量以及修改成员变量名),然后从该文件中取出了person类的对象。那么便存在着一个问题,就是从person类中取出来的对象是旧的person类,而现在的person.class文件是新得person类,旧的person类的成员变量与新的person类的成员变量不尽相同,引发了对person类两个不同版本的兼容性问题。

为了解决上述问题。Java序列机制中提供了private static final的serialVersionUID值,用于标识该Java类的序列化版本,若修改person类后,只要serialVersionUID的值与旧版本的值一致,序列机制也会把它们当成同一个序列化版本。

那么修改类的那么内容后,serialVersionUID无需修改值或者需要修改值呢?根据对象序列化主要注意的点中,对象序列化是对对象的类名,实例变量(static与transient修饰的成员变量不算)都会被序列化,因此若一个类修改了成员变量,添加了成员变量,删除了成员变量的情况,是需要进行修改serialVersionUID的值,除此之外是不用对serialVersionUID进行修改的。

总结:序列化机制允许将实现序列化的Java对象转换成字节序列,这些字节序列可以保存在磁盘上,或者用于网络传输,以备以后重新恢复成原来的对象。序列化机制使得对象可以脱离程序的运行而独立存在。

原文地址:https://www.cnblogs.com/hjlin/p/11432648.html

时间: 2024-11-14 12:00:20

IO流,对象序列化的相关文章

Java—IO流 对象的序列化和反序列化

序列化的基本操作 1.对象序列化,就是将Object转换成byte序列,反之叫对象的反序列化. 2.序列化流(ObjectOutputStream),writeObject 方法用于将对象写入输出流中: 反序列化流(ObjectInputStream),readObject 方法用于从输入流中读取对象. 3.序列化接口(Serializeable) 对象必须实现序列化接口,才能进行序列化,否则会出现异常.这个接口没有任何方法,只是一个标准. package com.test.io; import

java 21 - 13 IO流之序列化和反序列化

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输.对象 -- 流数据(ObjectOutputStream) 构造方法:ObjectInputStream(InputStream in)  创建从指定 InputStream 读取的 ObjectInputStream 反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象.流数据 -- 对象(ObjectInputStream) 构造方法:ObjectInputStream(InputStream in)  创建从指定

java核心学习(十七) IO框架---对象序列化

一.使用对象流实现序列化. 先定义一个可序列化的对象 package com.shy.IO; import java.io.Serializable; public class Person implements Serializable{ public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } publ

java -&gt;IO流_序列化流与反序列化流

序列化流与反序列化流 用于从流中读取对象的操作流 ObjectInputStream    称为 反序列化流 用于向流中写入对象的操作流 ObjectOutputStream   称为 序列化流(对象保存到文件中) l  特点:用于操作对象.可以将对象写入到文件中,也可以从文件中读取对象. 对象序列化流ObjectOutputStream ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream.可以使用 ObjectInputStream 读取

笔记:I/O流-对象序列化

Java 语言支持一种称为对象序列化(Object Serialization)的非常通用的机制,可以将任何对象写入到流中,并在之后将其读回,首先需要支持对象序列化的类,必须继承与 Serializable 接口,该接口没有任何方法,只是对类起到标记的作用,然后使用 ObjectOutputStream 流来序列化对象,使用 ObjectInputStream 流来反序列化,示例代码如下: 对象类声明: public class Employee implements Serializable

阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_09 序列化流_3_对象的反序列化流_ObjectInputStream

声明了IO异常,这里还是红色的 转换为Person对象 原文地址:https://www.cnblogs.com/wangjunwei/p/11273536.html

阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_09 序列化流_2_对象的序列化流_ObjectOutputStream

创建person对象.生成构造方法全参和无参.getter和setter 抛出异常:没有序列化异常 接口的源码 啥都没有.就起到一个标记的作用 用二进制存的 原文地址:https://www.cnblogs.com/wangjunwei/p/11273498.html

io流和序列化

1.使用File操作文件 public class IoTest { public static void main(String[] args) throws IOException { /* 01.删除或者创建文件 * File file=new File("e:/io.txt"); addOrDel(file); */ File file=new File("e:/java/hello"); //file.mkdir(); 只能创建一层目录 file.mkdi

java io流与序列化反序列化

java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作. 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象. 下面是一个实例,通过例子来将以上来简化学习: 1.先创建一个学生类来实现serialization: 1 package com.etc; 2 3 import java.io.Serializable; 4

阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_09 序列化流_4_transient关键字_瞬态关键字

不想被序列化的成员变量用 transient修饰 age加上static关键字 反序列化age就读取不到正确的值了 原文地址:https://www.cnblogs.com/wangjunwei/p/11273552.html