序列化
將堆內存中的對象數據,通過序列化存儲到磁盤或者傳遞給其他網絡節點的過程稱為序列化,反之稱為反序列化。
序列化細節
需要序列化的類必須實現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");
}
}