序列化
将堆内存中的对象数据,通过序列化存储到磁盘或者传递给其他网络节点的过程称为序列化,反之称为反序列化。
序列化细节
需要序列化的类必须实现Serializable接口(标记接口,没有任何抽象方法),引用序列化的类,也需要实现Serializable接口。
反序列化创建对象时,不会调用构造方法。
serialVersionUID
通过类名、成员、包名、工程名算出的一个数字,用于记录class文件的版本信息。
反序列化时,ObjectInputStream会先读取文件中的serialVersionUID,再与本地class文件的serialVersionUID进行对比,如果ID号不一致,则读取失败,以此来保证两个文件兼容相同。
如果类中某个属性不想被序列化,则用transient修饰。
class Demo implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String demo; //忽略的数据
public Demo(String name, int age, String demo) {
this.name = name;
this.age = age;
this.demo = demo;
}
@Override
public String toString() {
return "Demo{" +
"name='" + name + '\'' +
", age=" + age +
", demo='" + demo + '\'' +
'}';
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
File file = new File("E:", "Demo.txt");
Demo demo = new Demo("Demo", 18, "Transient");
ObjectOutputStream objos = new ObjectOutputStream(
new FileOutputStream(file));
objos.writeObject(demo);
objos.close();
ObjectInputStream objis = new ObjectInputStream(
new FileInputStream(file));
Demo readDemo = (Demo) objis.readObject();
System.out.println(readDemo);
}
浅克隆
就是将目标对象克隆一份,相当于将目标对象堆内存中的内容克隆一份。
浅克隆细节
需要被克隆的类必须实现Cloneable接口(标识接口,没有任何方法)。
在克隆一个对象的时,如果被克隆的对象中维护了另外一个类的对象,这时只是克隆了另外一个对象的地址,并没有把另外一个对象克隆。
浅克隆不会调用构造方法。
public static void main(String[] args) throws CloneNotSupportedException {
Demo demo = new Demo("Demo", 18);
Demo cloneDemo = (Demo) demo.clone();
System.out.println(cloneDemo.name);
}
class Demo implements Cloneable {
public String name;
public int age;
public Demo(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
Properties加载资源文件
配置文件,即资源文件(以.properties为扩展名的文件)。
主要用于生成配置文件与读取配置文件,属于Map集合的一个实现类。
public class Run {
public static void main(String[] args) throws IOException {
loadProperties();
}
// 创建
public static void createProperties() throws IOException {
Properties properties = new Properties();
properties.setProperty("Test1", "Vaule1");
properties.setProperty("测试", "Vaule2");
properties.setProperty("Test3", "Vaule3");
第一个参数是输出流对象,第二个参数是文件名称
// properties.store(new FileOutputStream("D:","Test.properties"), "Test");
properties.store(new FileWriter("D:","Test.properties"), "测试配置文件");
}
// 读取
public static void loadProperties() throws IOException {
Properties properties = new Properties();
properties.load(new FileReader("D:","Test.properties"));
for (Entry<Object, Object> map : properties.entrySet()) {
System.out.println(map.getKey() + ":" + map.getValue());
}
//修改信息
properties.setProperty("Test3", "Test");
//修改后重新存储
properties.store(new FileWriter("D:","Test.properties"), "测试配置文件");
}
}
//检查登录次数
public class Run {
public static void main(String[] args) throws IOException {
checkRuntimeCount();
}
public static void checkRuntimeCount() throws IOException {
String filePath = "D:" + File.separator + "runTime.properties";
File curFile = new File(filePath);
if (!curFile.exists()) {
curFile.createNewFile();
}
Properties properties = new Properties();
properties.load(new FileInputStream(filePath));
int count = 0;
String value = properties.getProperty("count");
if (value != null) {
count = Integer.parseInt(value);
}
if (count == 3) {
System.out.println("已经使用超过三次");
System.exit(0);
}
count++;
System.out.println("已经使用" + count + "次");
properties.setProperty("count", count + "");
properties.store(new FileOutputStream(curFile), "count");
}
}