Java提供了一种对象序列化的机制,用一个字节序列能够表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写入到文件中后,就至关于在文件中保存了一个对象信息。java
反之,该字节序列还能够从文件读取出来,重构对象,对它进行反序列化。对象的数据、对象的类型和对象中存储的数据信息,均可以用来在内存中建立对象。ide
java.io.ObjectOutputStream
类,将Java对象的原始数据类型写入到文件中,实现对象的持久化存储。this
一个对象想要可以序列化和反序列化,必须知足两个条件:code
该类必须实现java.io.Serializable
接口,Serializable接口,是一个标记型接口,若是该类没有实现Serializable接口,将会抛出NotSerializableException。对象
该类的全部属性必须是能够实现序列化或者反序列化。若是有一个属性不想让它参与序列化,则该属性必须标明是瞬态的,瞬时的,这个关键字是transient
。blog
public class Student implements Serializable { private String name; private transient Integer age;// 不让age属性参与序列化 }
java.io.ObjectInputStream
类是反序列化流,将以前使用ObjectOutputStream序列化流的原始数据恢复为对象。接口
对于JVM来讲,可以进行反序列的对象 ,前提条件是必须可以找到class文件的类,若是找不到该类的class文件,则会抛出一个ClassNotFoundException异常。内存
另外,当JVM序列化对象时,可以找到class文件,可是class文件在序列化对象时,发生了修改,那么反序列化操作会抛出一个InvalidClassException异常。缘由以下:资源
该类的序列化版本号与从流中读取出来描述该类的版本号不一致。get
该类包含了未知数据类型。
该类没有可访问的无参构造方法。
Serializable接口给须要序列化的类,提供了一个序列化版本号,serialVersionUID 该版本号的目的就是在于验证序列化的对象和对应的类是不是版本一致的。
代码演示:
// 序列化操做类 public class Demo01ObjectOutputStream { public static void main(String[] args) throws IOException { //1.建立ObjectOutputStream流对象,构造方法中传递指定的字节输出流。 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day30_IO\\student.txt")); //2.使用ObjectOutputStream对象中的方法writeObject,把对象写入到文件中。 //2.1 先建立一个对象 Student s = new Student("小孙", 30); s.score = 60; //2.2写对象到文件中 oos.writeObject(s); //3.释放资源。 oos.close(); } } // 反序列化类操做 public class Demo02ObjectInputStream { public static void main(String[] args) throws IOException, ClassNotFoundException { // 1. 建立一个ObjectInputStream流对象,构造方法中传递一个字节输入流对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day30_IO\\student.txt")); // 2. 使用ObjectInputStream流对象中的方法readObject,读取保存在文件中的对象数据 Object obj = ois.readObject(); // 3.释放资源。 ois.close(); // 4. 查看对象的数据 System.out.println(obj);// Student{name='小孙', age=30} if ( obj instanceof Student) { Student student = (Student)obj; System.out.println(student.getAge() + "--" + student.getName()); } else { System.out.println("转换失败"); } } } // 须要被序列化的类 import java.io.Serializable; public class Student implements Serializable { // 能够选择手动自定义一个序列化版本号 private static final long serialVersionUID = 1L; //private static String name; private String name; private Integer age; private transient String address = "郑州市"; transient int score;// 0 }
原理分析:
import java.io.Serializable; public class Student implements Serializable { // 能够选择手动自定义一个序列化版本号 private static final long serialVersionUID = 1L; //private static String name; private String name; private Integer age; private transient String address = "郑州市"; transient int score;// 0 public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Student() { } public Student(String name, Integer age) { this.name = name; this.age = age; address = "郑州市"; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + ", score=" + score + '}'; } } @SuppressWarnings("unchecked") public class DemoTestSerialize { public static void main(String[] args) throws IOException, ClassNotFoundException { //1.定义多个对象,存储在集合中 ArrayList<Student> list = new ArrayList<>(); list.add(new Student("小孙",30)); list.add(new Student("小王",20)); list.add(new Student("小赵",40)); list.add(new Student("小刘",10)); list.add(new Student("小丽",25)); //2.使用序列化技术,把该集合对象写入到文件中 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day30_IO\\student.txt")); //3.写入进去,调用writeObject oos.writeObject(list); //4.使用反序列化技术,把文件中保存的集合对象读取出来 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day3_IO\\student.txt")); //5.读取对象数据,调用readObject()方法 Object obj = ois.readObject(); //6.向下转型 if (obj instanceof ArrayList){ ArrayList<Student> students = (ArrayList<Student>)obj; //7.遍历该集合对象 for (Object student:students){ System.out.println(student); } } } }
java.io.PrintStream
类可以很方便打印各类数据类型的值。
正常System.out就是PrintStream类型的,数据的流动的位置在控制台中。改变数据的流动位置。经过System.setOut(PrintStream print)来改变流向。
PrintStream out = System.out; out.print(123);// 在控制台中 // 构造方法建立一个打印流对象 PrintStream printStream = new PrintStream("day30_IO\\print.txt"); // 改变打印流的方向为"day30_IO\\print.txt"路径 System.setOut(printStream); System.out.println("我已经改变了输出数据的位置"); System.out.println("我想在控制台中输出数据"); System.out.println("啦啦啦啦啦");