> Java > java지도 시간 > 본문

JAVA 직렬화

黄舟
풀어 주다: 2017-02-24 09:44:30
원래의
1524명이 탐색했습니다.

1. 문제:

객체를 파일에 쓰려는 경우 바이트 스트림이나 문자 스트림 모두를 충족할 수 없습니다. 파일에 개체를 쓰는 방법은 무엇입니까?
바이트 문자 스트림을 사용할 때는 객체를 바이트/문자로 변환한 후 파일에 써야 합니다. 그러나 바이트 문자 스트림에는 객체를 바이트로 변환하는 방법이 없습니다. 이걸 해?

2. 직렬화 및 역직렬화

Java 직렬화: 객체를 바이트로 변환하는 프로세스로, 내 요구 사항을 정확히 충족합니다.
Java 역직렬화: 바이트를 객체로 복원하는 프로세스
이는 객체를 파일에 쓰고 객체를 읽으려는 우리의 욕구를 충족합니다

3, 직렬화 및 역직렬화 사용 시나리오

  • a. 개체를 하드 디스크에 씁니다.

  • b. 네트워크 간 전송

    • , 오디오, 비디오 등이 네트워크를 통해 전송되면 전송을 위해 이진 시퀀스로 변환됩니다. 네트워크를 통해 개체를 전송하려면 직렬화 및 역직렬화를 사용하여 데이터 전송 및 수신을 충족해야 합니다.

      ###4. 직렬화 및 역직렬화의 이점
      1. 직렬화를 통해 데이터 지속성을 확보하고 데이터를 로컬 하드 디스크에 영구 저장합니다.
      2. 객체는 네트워크를 통해 전송될 수 있습니다.

5. 직렬화 및 역직렬화 구현 방법

5.1

직렬화 가능 인터페이스

구현 메소드는 아니며 단지 이 클래스가 직렬화될 수 있음을 Java 메커니즘에 알리는 식별자를 제공할 뿐입니다. 이 식별자가 생성되지 않으면 Java 메커니즘은

클래스 이름, 인터페이스 이름, 멤버 메서드 및 속성
등을 기반으로 64비트 해시 필드를 생성합니다. .

    SerialVersionUID가 없는 경우 일반적으로 직렬화 후 클래스의 속성이 수정되면 역직렬화 중에 오류가 보고됩니다. 피곤한 속성이 수정되었기 때문입니다. java 메커니즘은 SerialVersionUID를 다시 생성하므로 원래 ID와 불일치하고 역직렬화 오류가 발생합니다.

    • SerialVersionUID 구현이 설정되어 있으면 버전 호환성이 보장됩니다. 속성이나 메소드를 추가하더라도 직렬화 및 역직렬화는 가능합니다.
    • 새로 추가된 속성의 값이 null이거나 삭제된 속성의 값이 표시되지 않습니다.

    • package com.chb.test;import java.io.Serializable;public class Student implements Serializable{
          //序列化标识
          private static final long serialVersionUID = 1L;    
          private String name;    
          private int age;    
          private String sex;    
          public Student() {
          }    
          public Student(String name, int age, String sex) {        
          super();        
          this.name = name;        
          this.age = age;        
          this.sex = sex;
          }    
          @Override
          public String toString() {        
          return "Student{"
                      +"姓名:"+this.name
                      +"性别:"+this.sex
                      +"年龄"+this.age
                      + "}";
          }    
          /**setter getter 省略。。。*/    
          }
      로그인 후 복사
    5.2, ObjectOutputStream 및 ObjectInputStream

Serializalable 인터페이스는 객체를 바이너리 시퀀스로 변환하고 바이너리 시퀀스를 객체로 복원하는 표현만 제공합니다. ObjectOutputStream 및 ObjectInputStream에서 제공하는 두 가지 메서드는 writeObject() 및 readObject()

    writeObject()
  • public static void write(Student s1) throws Exception {
            FileOutputStream fos = new FileOutputStream(filename);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(s1);
            oos.close();
    }
    로그인 후 복사
    로그인 후 복사
    입니다. readObject()
  • public static Student read() throws Exception {
            FileInputStream fis = new FileInputStream(filename);
            ObjectInputStream ois = new ObjectInputStream(fis);
            Student stu = new Student();        //使用readeObject()进行反序列化
            stu= (Student) ois.readObject();
            ois.close();        return stu;
    }
    로그인 후 복사
    로그인 후 복사
  • 6.transient

어떤 경우에는 특정 민감한 필드를 직렬화하고 싶지 않거나 클래스의 참조 유형 멤버가 직렬화가 불가능합니다. . 이것이 직렬화되는 것을 방지하기 위해

transient

를 사용하여 이러한 멤버를 수정해야 하는 이유입니다. 예: 은행 계좌 개체, 계좌 금액을 직렬화하고 싶지 않습니다. 위 Student 클래스를 수정하고, 임시

transient private String sex;
로그인 후 복사
로그인 후 복사

로 sex 속성을 수정한 다음 역직렬화를 위해

Student s1 = new Student("roase",19, "女");
write(s1);
로그인 후 복사
로그인 후 복사

를 직렬화합니다. 읽기 개체가 발견되었습니다. sex는 null이며 일시적임을 나타냅니다. 수정된 속성은 직렬화되지 않습니다.


JAVA 직렬화6.1 defaultWriteObject 및 defaultReadObject()

위 임시 멤버 연령의 경우 여기서 직렬화 및 역직렬화할 수 있도록 하려면 어떻게 해야 할까요?

    1. 임시 수정을 제거합니다
  • 2. writeObject( ) 메서드를 사용하면 ObjectOutputStream의 defaultWriteObject() 메서드가 먼저 호출됩니다. 이 메서드는
  • 기본 직렬화 메커니즘

    을 실행하며 age 필드는 무시됩니다. 그런 다음 writeInt() 메서드를 호출하여 연령 필드를 ObjectOutputStream에 명시적으로 씁니다. readObject()의 기능은 객체를 읽는 것이며, 그 원리는 writeObject() 메소드와 동일합니다. read() 애플리케이션을 다시 실행하면 다음과 같은 결과가 출력됩니다.

1. 질문:

 객체를 file , 바이트 스트림이나 문자 스트림 모두 요구 사항을 충족할 수 없음을 발견했습니다.

객체를 파일에 쓰는 방법은 무엇입니까? JAVA 직렬화

바이트 문자 스트림을 사용할 때는 객체를 바이트/문자로 변환한 후 파일에 써야 합니다. 그러나 바이트 문자 스트림에는 객체를 바이트로 변환하는 방법이 없습니다. 이것?

2、序列化与反序列化

Java序列化:将对象转为字节的过程,这正好符合我的需求。
Java反序列化:将字节恢复为对象的过程
这满足我们想文件中写对象,和读取对象

3、序列化和反序列化的使用场景

  • a、将对象写道硬盘中;

  • b、网络间传输

    • 当在网络上传送文本,音频,视频等,都是转化为二进制序列传送,我们要在网络上传送对象,就必须使用序列化和反序列化,满足数据的发送和接收。
      ###4、序列化和反序列化的好处
      一、实现数据的持久化,通过序列化将数据永久的保存在本地的硬盘上;
      二、实现远程网络通信,利用序列化,使得在网络上可以传输对象的字节序列。

5、如何实现序列化和反序列化

5.1 、实现Serializable接口

  Serializable接口没有任何方法,只是提供一个标识 , 用来告诉java机制该类可以被序列化;
   如果没有创建这个标识,java机制将会自动的创建一个,SerialVersionUID是根据类名, 接口名,成员方法及属性等来生成一个64位哈希字段

  • 如果没有SerialVersionUID, 通常我们会发现,如果在序列化后,修改了类的属性, 在进行反序化,会报错,因为累的属性修改了,java机制会重新创建一个SerialVersionUID, 导致与原来的ID不一致, 反序列化失败。

    • 如果设置了实现SerialVersionUID, 保证版本的兼容性, 即使添加了属性或方法, 仍然能进行序列化和反序列化, 只是新添加的属性值为null,或不显示被删除属性的值。

package com.chb.test;import java.io.Serializable;public class Student implements Serializable{
    //序列化标识
    private static final long serialVersionUID = 1L;    
    private String name;    
    private int age;    
    private String sex;    
    public Student() {
    }    
    public Student(String name, int age, String sex) {        
    super();        
    this.name = name;        
    this.age = age;        
    this.sex = sex;
    }    
    @Override
    public String toString() {        
    return "Student{"
                +"姓名:"+this.name
                +"性别:"+this.sex
                +"年龄"+this.age
                + "}";
    }    
    /**setter getter 省略。。。*/    }
로그인 후 복사

5.2、ObjectOutputStream与ObjectInputStream

  Serializalable接口只是提供一个表示,将对象转为二进制序列,和二进制序列恢复成对象是由ObjectOutputStream和OjbectInputStream提供的两个方法:writeObject()和readObject()

  • writeObject()

public static void write(Student s1) throws Exception {
        FileOutputStream fos = new FileOutputStream(filename);
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(s1);
        oos.close();
}
로그인 후 복사
로그인 후 복사
  • readObject()

public static Student read() throws Exception {
        FileInputStream fis = new FileInputStream(filename);
        ObjectInputStream ois = new ObjectInputStream(fis);
        Student stu = new Student();        //使用readeObject()进行反序列化
        stu= (Student) ois.readObject();
        ois.close();        return stu;
}
로그인 후 복사
로그인 후 복사

6、transient

在某种场合,我们对某些敏感字段不要进行序列化,或者类的引用类型的成员不能够进行序列化, 这是我们需要使用transient来修饰这些成员, 以避免它们被序列化。如:银行账户对象,不希望对账户金额进行序列化。
修改上面的Student类,将sex属性使用transient修饰

transient private String sex;
로그인 후 복사
로그인 후 복사

再进行序列化

Student s1 = new Student("roase",19, "女");
write(s1);
로그인 후 복사
로그인 후 복사

反序列化, 读取的对象发现:sex为null,说明被transient修饰的属性不会被序列化。
JAVA 직렬화

6.1 defaultWriteObject和defaultReadObject()

对于上面的被transient的成员age, 如果我们想让它能够在此序列化和反序列化,要如何做:

  • 1、去掉transient的修饰

  • 2、提供两个方法

    private void writeObject(ObjectOutputStream out) throws Exception{        
    out.defaultWriteObject();        
    out.writeInt(age);
    }    
    private void  readObject(ObjectInputStream in) throws Exception {        
    in.defaultReadObject();
        age=in.readInt();
    }
로그인 후 복사

在writeObject()方法中会先调用ObjectOutputStream中的defaultWriteObject()方法,该方法会执行默认的序列化机制,此时会忽略掉age字段。然后再调用writeInt()方法显示地将age字段写入到ObjectOutputStream中。readObject()的作用则是针对对象的读取,其原理与writeObject()方法相同。再次执行read()应用程序,则又会有如下输出:

JAVA 직렬화

 以上就是JAVA之序列化的内容,更多相关内容请关注PHP中文网(www.php.cn)!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿