系统流
-
err、out、in 都是字节流
-
Scanner sc=new Scanner(System.in);
-
System.out.println(); // System.err.println(); // 红色字体
-
-
系统流是静态的,不需要关流
序列化与反序列化
- 序列化是将对象按字节顺序进行存储,并且在以后需要时重新还原它们(称为反序列化)的一种机制。
- 可以通过序列化机制,将一个对象保存在文件中,或通过网络传送到另一台计算机上。
- 标准类库中的大多数类的实例都是可序列化的,如包裹类、String类、集合类、数组等等。
public class TestObjectOutputStream {
public static void main(String[] args) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("./testOS.dat");
bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
Integer num = 123;
oos.writeObject(num);
int[] nums = {11, 22, 33, 44, 55};
oos.writeObject(nums);
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("def");
list.add("uvw");
list.add("xyz");
oos.writeObject(list);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
}
}
}
}
}
public class TestObjectInputStream {
public static void main(String[] args) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("./testOS.dat");
ois = new ObjectInputStream(fis);
Integer num = (Integer)ois.readObject();
System.out.println(num);
int[] nums = (int[])ois.readObject();
for (int n : nums) {
System.out.print(n + " ");
}
System.out.println();
List<String> list = (List<String>)ois.readObject();
System.out.println(list);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
}
}
}
}
}
对象序列化规则
- 当对象被序列化时,JVM只序列化其字段值,方法和构造器不参与序列化。
- 如果对象的某个字段引用了另一个对象,则被引用对象的字段也将被序列化。
- 被应用对象的类也需要实现Serializable接口
- Java中的包裹类和String都实现了Serializable接口
- Java中常用的集合实现类和Map集合实现类都实现了Serializable接口
- 如果某个属性不想参与序列化,可以使用
transient
进行修饰 - 有些对象类(如FileInputStream)是不可序列化的,因为其字段值是与操作系统相关的即时信息。
- 访问控制修饰符(public、protected、default和private)对序列化的数据字段没有任何影响。
- 静态变量不参与序列化,因为它们不属于对象。
自定义序列化
- 对于应用程序自定义的类,必须实现java.io.Serializable接口,其对象才能参与序列化。
- java.io.Serializable接口中没有方法,它仅作为一个标记,用于表示实现该接口的类可以用于序列化。
- 如果类中某些字段包含了对不可序列化对象的引用,或有的字段不需要参与序列化,只要将其修饰为transient即可。
serialVersionUID
-
当一个类实现了java.io.Serializable接口后,可以显式的在类中声明一个属性,作为该类的标识,用于验证序列化和反序列化使用的类是否一致:
-
private static final long serialVersionUID = -5810487980130256753L;
-
在序列化该类的对象时,这一串数字会被优先写入数据中
-
当反序列化时,会先验证当前环境下使用的类的serialVersionUID与数据中保存的serialVersionUID是否一致,如果一致,则继续进行反序列化,如果不一致,则直接抛出异常
public class Student implements Serializable {
private int id;
private String name;
private int age;
private transient double score;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
// get/set Method......
// toString Method……
// ……
}
public class TestSerialization {
public static void main(String[] args) {
FileOutputStream fos = null;
BufferedOutputStream bos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("./testSer.dat");
bos = new BufferedOutputStream(fos);
oos = new ObjectOutputStream(bos);
Student s1 = new Student(1, "zhang", 20);
oos.writeObject(s1);
Student s2 = new Student(2, "li", 30);
oos.writeObject(s2);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
}
}
}
}
}
public class TestDeserialization {
public static void main(String[] args) {
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream("./testSer.dat");
ois = new ObjectInputStream(fis);
Student stu1 = (Student)ois.readObject();
System.out.println(stu1);
Student stu2 = (Student)ois.readObject();
System.out.println(stu2);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
}
}
}
}
}
练习:
- 编写Person类,包含姓名、年龄、体重等属性,提供对应的访问方法;
- 编写测试类1,在main方法中创建三个不同的Person对象,将这三个对象序列化到文件中;
- 编写测试类2,在main方法中从文件中反序列化三个Person对象,打印输出。验证序列化的正确;
- 在测试类1中,将三个Person对象放到数组中,序列化该数组到一个独立的文件中。再将三个Person对象放到List集合中,序列化该集合到另一个独立的文件中;
- 在测试类2中,将三个Person对象从数组文件中反序列化,并打印;
- 将三个Person对象从List集合文件中反序列,并打印。验证数组对象和集合对象的序列化。
Properties
- .perperties是较为常用的配置信息文件
name=张三
age=18
gender=女
age=20
- 例如以后连接数据库的配置
url=jdbc:mysql://localhost:3306/testdb
driver=com.mysql.jdbc.Driver
username=root
password=123456
-
Java提供的用于读写.properties文件的工具类
-
以键值对形式保存数据,键和值都是字符串类型
-
文件内容出现中文默认使用UTF16进行编码
-
API设计:
- Properties prop=new Properties(); // 创建工具类对象
- prop.setProperties(“key”,“value”); // 添加一个键值对
- prop.store(new FileWriter(“p1.properties”)); // 将数据写入目标文件
- prop.load(new FileReader(“p1.properties”)); // 读取目标文件中的内容,自动封装成键值对
- String value=prop.getProperties(“key”); // 基于key读取对应value的值
- prop.list(System.out); // 列出所有映射的信息
设计模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。
什么是 GOF(四人帮,全拼 Gang of Four)?
在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,该书首次提到了软件开发中设计模式的概念。
四位作者合称 GOF(四人帮,全拼 Gang of Four)。他们所提出的设计模式主要是基于以下的面向对象设计原则。
- 对接口编程而不是对实现编程。
- 优先使用对象组合而不是继承。
设计模式的类型
根据设计模式的参考书 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。
装饰者模式
装饰者模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。
介绍
**意图:**动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
**主要解决:**一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
**何时使用:**在不想增加很多子类的情况下扩展类。
**如何解决:**将具体功能职责划分,同时继承装饰者模式。
关键代码: 1、Component 类充当抽象角色,不应该具体实现。 2、修饰类引用和继承 Component 类,具体扩展类重写父类方法。
应用实例: 1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
**优点:**装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
**缺点:**多层装饰比较复杂。
使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。
**注意事项:**可代替继承。
单元测试
- 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。
- 单元就是人为规定的最小的被测功能模块。在Java中,小到一个方法,大到一整个类,都可以是一个单元。
- 单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
JUnit
- JUnit是一个Java语言的单元测试框架。
- 它由Kent Beck和Erich Gamma建立,逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。
- JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。