JavaSE_Serializable
1、什么是对象的序列化和反序列化?对象的序列化和反序列化有什么作用?
对象的序列化:将java对象转化为二进制编码!
对象的反序列化:将二进制编码转化为java对象!
序列化和反序列化的作用:可以将对象进行长期的保存;序列化后的对象便于网络传输;可以实现对象的深克隆!
2、实现Serializable接口:
- (1):Serializable接口为空接口,
作用:在标示该对象是否能被序列化,如果被序列化的对象不实现Serializable接口,那么会抛出java.io.NotSerializableException异常。 - (2):需要指定序列化版本ID
作用:标示这个类的唯一性。 - (3):可以使用transient关键字屏蔽一个属性:
作用:使用了transient关键字标示一个属性,那么该属性则不会被序列化。
3:实现Externalizable接口:
- (1):Externalizable接口继承自Serializable接口,提供了两个方法。
void writeExternal(ObjectOutput out)方法:作用可以指定序列化的属性。
void readExternal(ObjectInput in)方法:作用可以指定反序列化的属性。 - (2):不需要指定序列化的版本ID
- (3):可以通过不向writeExternal方法与readExternal方法写入属性的方式屏蔽属性。
- (4):序列化对象必须提供一个无参的构造方法,否则会抛出:java.io.InvalidClassException异常。
原因:通过实现Externalizable接口完成序列化的方式反序列化对象时先在系统中创建出该对象,由于没有提供无参构造方法则无法创建初始对象。
4:对比:
实现Serializable接口比实现Externalizable接口序列化对象性能略高一点点,但是实现Serializable接口简单。
涉及到屏蔽属性:如果要屏蔽的属性特别多则实现Externalizable接口反之实现Serializable接口。
5:对象的序列化和反序列化代码实现。
// 实现对Product类的序列化和反序列化
public class Test {
public static void main(String[] args) {
Product product_1 = new Product("小米手机", 10000.0, 0.8, 15);
Product product_2 = new Product("红米手机", 12000, 0.9, 20);
/**
* 将多个对象序列化到一个文件中:方法1:直接序列化。
*/
// 将对象序列化。(可以将多个对象序列化到一个文件中。)
try(ObjectOutputStream out = new ObjectOutputStream
(new BufferedOutputStream(new FileOutputStream("D:\\MyJava Code\\JavaSE_OOP\\data\\Product.ser")))) {
out.writeObject(product_1);
out.writeObject(product_2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 将一个文件反序列化。(也可以将一个文件中序列化出多个对象。)
try(ObjectInputStream in = new ObjectInputStream
(new BufferedInputStream(new FileInputStream("D:\\MyJava Code\\JavaSE_OOP\\data\\Product.ser")))) {
// 返回值为Object类型需要进行强制类型转换。
Product inProduct_1 = (Product) in.readObject();
Product inProduct_2 = (Product) in.readObject();
System.out.println(inProduct_1);
System.out.println(inProduct_2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("-------------------------------------------------------------");
/**
* 将多个文件序列化到一个文件中:方法2:使用集合:可以避免频繁的进行读写操作。
*/
List<Product> list = new ArrayList<Product>();
list.add(product_1);
list.add(product_2);
// 将集合对象序列化。(可以将多个对象序列化到一个文件中。)
try(ObjectOutputStream out = new ObjectOutputStream
(new BufferedOutputStream(new FileOutputStream("D:\\MyJava Code\\JavaSE_OOP\\data\\ProductList.ser")))) {
out.writeObject(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 将一个文件反序列化。(也可以将一个文件中序列化出多个对象。)
try(ObjectInputStream in = new ObjectInputStream
(new BufferedInputStream(new FileInputStream("D:\\MyJava Code\\JavaSE_OOP\\data\\ProductList.ser")))) {
// 返回值为Object类型需要进行强制类型转换。
@SuppressWarnings("unchecked")
List<Product> inList = (List<Product>) in.readObject();
System.out.println(inList);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("-------------------------------------------------------------");
/**
*
* 测试Admin类:
*
*/
Admin admin = new Admin("asdfghj", 1234567, LocalDateTime.now());
// 将集合对象序列化。(可以将多个对象序列化到一个文件中。)
try(ObjectOutputStream out = new ObjectOutputStream
(new BufferedOutputStream(new FileOutputStream("D:\\MyJava Code\\JavaSE_OOP\\data\\Admin.ser")))) {
out.writeObject(admin);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 将一个文件反序列化。(也可以将一个文件中序列化出多个对象。)
try(ObjectInputStream in = new ObjectInputStream
(new BufferedInputStream(new FileInputStream("D:\\MyJava Code\\JavaSE_OOP\\data\\Admin.ser")))) {
// 返回值为Object类型需要进行强制类型转换。
Admin inAdmin = (Admin) in.readObject();
System.out.println(inAdmin);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 第一种实现Serializable接口
*/
class Product implements Serializable{
/**
* 序列化版本ID。
*/
private static final long serialVersionUID = 3272573934111864077L;
private String productName; // 商品的名称
private double price; // 商品的价格
private double sale; // 商品的折扣
// 使用关键字transient屏蔽商品库存的属性。
private transient int count; // 商品的库存
public Product(String productName, double price, double sale, int count) {
this.productName = productName;
this.price = price;
this.sale = sale;
this.count = count;
}
@Override
public String toString() {
return "Product [productName=" + productName + ", price=" + price + ", sale=" + sale + ", count=" + count + "]";
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public double getSale() {
return sale;
}
public void setSale(double sale) {
this.sale = sale;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
/**
* 第二种:实现Externalizable接口
*/
class Admin implements Externalizable{
private String loginPhoneNumber; // 登录手机号码
private int loginPassword; // 登录密码
private LocalDateTime lastLoginDateTime; // 最后登录时间
public Admin() {
}
public Admin(String loginPhoneNumber, int loginPassword, LocalDateTime lastLoginDateTime) {
this.loginPhoneNumber = loginPhoneNumber;
this.loginPassword = loginPassword;
this.lastLoginDateTime = lastLoginDateTime;
}
@Override
public String toString() {
return "Admin [loginPhoneNumber=" + loginPhoneNumber + ", loginPassword=" + loginPassword
+ ", lastLoginDateTime=" + lastLoginDateTime + "]";
}
public String getLoginPhoneNumber() {
return loginPhoneNumber;
}
public void setLoginPhoneNumber(String loginPhoneNumber) {
this.loginPhoneNumber = loginPhoneNumber;
}
public int getLoginPassword() {
return loginPassword;
}
public void setLoginPassword(int loginPassword) {
this.loginPassword = loginPassword;
}
public LocalDateTime getLastLoginDateTime() {
return lastLoginDateTime;
}
public void setLastLoginDateTime(LocalDateTime lastLoginDateTime) {
this.lastLoginDateTime = lastLoginDateTime;
}
// 屏蔽密码属性
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(this.loginPhoneNumber);
//out.writeInt(this.loginPassword);
out.writeObject(this.lastLoginDateTime);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.loginPhoneNumber = in.readUTF();
//this.loginPassword = in.readInt();
this.lastLoginDateTime = (LocalDateTime) in.readObject();
}
}
5、相关类:
-
java.io.Externalizable接口
void writeExternal(ObjectOutput out)方法:可以指定序列化的属性。
void readExternal(ObjectInput in)方法:可以指定反序列化的属性。
-
java.io.ObjectInputStream类
Object readObject()方法:将一个二进制编码集转化为Object对象。
-
java.io.ObjectOutputStream类
void writeObject(Object obj)方法:将obj对象转化为二进制编码集。
-
java.io.Serializable接口
空接口