javaSE 笔记 标准输入流 + 标准输出流 + 对象序列化/反序列化流 + properties

标准输入流

因为是 public static final InputStream in 标准输入流,被static修饰,说明可以通过类名访问System.in
不过现在不太明白InputStream is = System.in;的用法<,
System类中有两个静态的成员变量:
public static final InputStream in 标准输入流
public static final PrintStream out 标准输出流
in,out,还有个err方法都是叫字段,而且似乎叫做类字段。

用字符缓冲输入流按行读取键盘输入的值:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
这边的 new BufferedReader(new InputStreamReader)是将字节流通过转换流转换成字符流,再转成字符缓冲输入流
不过这样写还是太麻烦了,所以JAVA提供了一个类供我们使用,即Scanner sc = new Scanner(System.in)

标准输出流

PrintStream ps = System.out; PrintStream 是OutputStream的子类
ps.println("xxx") = System.out.println("xxx")
输出语句的本质是一个标准的输出流,PrintStream类有的方法,System.out都可以使用

打印流

字节打印流: PrintStream 字符打印流 PrintWruter
PrintStream(String fileName):使用指定的文件名创建新的打印流
特点:只负责输出数据,不负责读取数据,有自己的特有方法,即使用继承父类的方法写数据ps.write(),查看的时候会转码,a会变成97,使用
自己的特有方法写数据ps.println(),查看的数据原样输出。

字符打印流:PrintWriter
主要有两个构造方法:PrintWriter(String fileWriter) PrintWriter(Writer out,boolean autoFlush)
第二种构造更重要,是为了自动刷新设计的,又因为Writer是抽象类,所以在构造的时候,只能传入它的子类FileWriter,多态的功能。
eg:PrintWriter pw = new PrintWriter(new FileWriter("xxx.txt"),true);
pw.println("hello"); // 这样就不需要加pw.flush()才能写入,另外这里的println也是一种特有的写数据方法吧

复制java文件可以用字符打印流改进,不过也只是在文件写入的时候能用PrintStream而已,看黑马视频P316

对象序列化流

就是将对象保存到磁盘中,或者在网络中传输对象。
这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息,字节序列写到
文件之后,相当于文件中持久保存了一个对象的信息。反之,该字节序列还可以从文件中读取出来,重构对象,对它进行反序列化。
要实现序列化和反序列化就要使用对象序列化流和对象反序列化流:
对象序列化流:ObjectOutputStream
对象反序列化流:ObjectInputStream
构造方法:ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
序列化对象的方法:writeObject(Object obj):将指定的对象写入ObjectOutputStream
eg:

    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("xxx.txt"));
    Student s = new Student("xxx",30);
    oos.writeObject(s);
    oos.close();

注意:一个对象想要被序列化,该对象所属的类必须实现Serializable接口
Serializable是一个标记接口,实现该接口,不需要重写任何方法。

对象反序列化流

ObjectInputStream 反序列化先前使用ObjectOutputStream编写的原始数据和对象
构造方法:ObjectInputStream(InputStream in)创建从指定的InputStream读取的ObjectInputStream
读取序列化对象的方法,readObject() 从ObjectInputStream读取一个对象

    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("xxx.txt"));
    Object obj = ois.readObject(s);  //  需要抛出异常
    Student s = (Student) obj;
    ois.close();

对象序列化流三个问题

1.用对象序列化流序列化了一个对象后,加入我们修改了对象所属的类文件,读取数据会不会出问题?
会出问题,报InvalidClassException,是因为类的串行版本与从流中读取的类描述符的类型不匹配,可以查看Serializable的中文文档
写和读的序列化版本不一样了,就报错。

2.如果出问题,怎么解决
在类中显示地定义一个序列化id,eg:private static dinal long serialVersionUID = 42L;这样即使修改了类的内容,也不会有啥问题。

3.如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
加上transient关键字,eg: private transient int age; 被这个关键字修饰的成员变量不参与序列化

Properties

Properties类表示一组持久的属性,是一个Map体系的集合类,可以保存到流中或从流中加载
因为没有泛型,所以只能这样创建集合对象, Properties prop = new Properties();同样也只能用put方法存储元素,另外
因为在创建对象的时候没办法<xx,xx>指定类型,所以取元素的时候默认是Object类型的

Properties作为集合的特有方法:Object setProperty(String key, String value) , String getProperty(String key) ,
Set stringPropertyNames() //从该属性列表中返回一个不可修改的键集。

上一篇:JavaSE——基础知识回顾21之反射与注解部分的案例


下一篇:JavaSE-Java基础面试题