Entity 실체 류 는 왜 Serializable 인 터 페 이 스 를 실현 해 야 직렬 화 됩 니까?

더 읽 기
       이 의문 을 일 으 키 는 것 은 Hibernate 에서 검색 캐 시 를 사용 하 는 것 부터 시작 합 니 다.대상 인 스 턴 스 는 메모리 외 에 도 2 급 캐 시 는 대상 을 하 드 디스크 에 기록 하여 필요 할 때 다시 읽 어 사용 합 니 다.이 때 는 하나의 개념 을 언급 해 야 합 니 다.직렬 화.
 
       프로그램 이 실 행 될 때 인 스 턴 스 대상 을 만 듭 니 다.이 대상 들 은 메모리 에 존재 합 니 다.프로그램 이 실 행 될 때 사라 집 니 다.그러나 일부 대상(일반적으로 서로 다른 속성)을 저장 하거나 다른 프로 세 스에 전송 하려 면 프로그램 이 실 행 된 후에 도 이러한 이미지 가 존재 합 니 다.프로그램 이 다시 실 행 될 때 이 대상 들 의 정 보 를 읽 을 수 있 습 니 다.또는 다른 프로그램 에서 저 장 된 대상 정 보 를 이용 하여 인 스 턴 스 대상 으로 복원 합 니 다.이런 상황 에서 대상 의 서열 화 와 반 서열 화 를 사용 해 야 한다.
       사실은 자바 에서 흔히 볼 수 있 는 몇 가지 유형,예 를 들 어 Interger/string 등 은 모두 자바.io.Serializable 인 터 페 이 스 를 실현 했다 는 것 을 일찍부터 알 고 있 었 다.이 직렬 화 인 터 페 이 스 는 아무런 방법 과 도 메 인 이 없고 표지 의 직렬 화 된 의미 에 만 사용 된다.Serializable 인 터 페 이 스 를 실현 하 는 클래스 는 직렬 화 될 수 있 으 며,이 인 터 페 이 스 를 실현 하지 않 은 클래스 는 직렬 화 되 거나 반 직렬 화 될 수 없습니다.직렬 화 류 의 모든 하위 클래스 자 체 는 직렬 화 될 수 있 으 며,Serializable 인 터 페 이 스 를 명시 적 으로 실현 할 필요 가 없습니다.직렬 화 를 거 쳐 야 대상 이 디스크 텍스트 와 네트워크 에서 의 전송,대상 을 복구 할 때 반 직렬 화 등 을 호 환 할 수 있 습 니 다.
 
문제 1:왜 서열 화 를 실현 해 야 합 니까?
답:직렬 화 는 인 스 턴 스 대상 의 상태(State 대상 속성 은 대상 방법 을 포함 하지 않 음)를 유 니 버 설 인 코딩(예 를 들 어 포맷 된 바이트 코드)하고 저장 하여 대상 의 완전 성과 전달 성 을 확보 하 는 것 입 니 다.
한 마디 로 하면 직렬 화 는 서로 다른 시간 이나 플랫폼 의 JVM 간 에 인 스 턴 스 대상 을 공유 하기 위 한 것 이다.
  
//       :
public static void main(String[] args) throws Exception {
    File file = new File("user.ser");

    ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
    User user = new User("zhang", 18, Gender.MALE);
    oout.writeObject(user);
    oout.close();

    ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
    Object newUser = oin.readObject();
    oin.close();
    System.out.println(newUser);
}

 
       Serializable 인터페이스 가 구현 되 지 않 으 면 직렬 화 할 때 Object Output Stream 의 write(object)방법 으로 대상 을 저장 할 때 이상 이 발생 합 니 다.실은 java.io.Serializable 은 속성 과 방법 이 없 는 빈 인터페이스 일 뿐 인 데 문제 가 생 겼 어 요...
 
문제 2:왜 꼭 실현 해 야 하 는가 Serializable 서열 화 를 할 수 있 을까요?
 
ObjectOutputStream 을 사용 하여 대상 을 지속 시 키 고, 이 곳 에서 던 진 이상 에 대해 서 는 다음 과 같이 확인 하 십시오.
 
private void writeObject0(Object obj, boolean unshared) throws IOException {
    // ...
            // remaining cases
            if (obj instanceof String) {
                writeString((String) obj, unshared);
            } else if (cl.isArray()) {
                writeArray(obj, desc, unshared);
            } else if (obj instanceof Enum) {
                writeEnum((Enum) obj, desc, unshared);
            } else if (obj instanceof Serializable) {
                writeOrdinaryObject(obj, desc, unshared);
            } else {
                if (extendedDebugInfo) {
                    throw new NotSerializableException(
                        cl.getName() + "
" + debugInfoStack.toString()); } else { throw new NotSerializableException(cl.getName()); } } // ... }
 이로부터 알 수 있다.
쓰기 대상 유형 이 String,배열,Enum,Serializable 이면 직렬 화 할 수 있 으 며,그렇지 않 으 면 NotSerializable Exception 을 던 집 니 다.
  
마지막 으로 주의:
1.직렬 화 대상 일 때 현재 대상 자 체 를 직렬 화 할 뿐만 아니 라 이 대상 이 인용 한 다른 대상 도 직렬 화 할 것 이다.이렇게 인용 전달 직렬 화.한 대상 에 포 함 된 구성원 변수 가 용기 류 등 이 고 심층 적 으로 인용 된다 면 직렬 화 과정 비용 도 비교적 크다.
2.필드 가 transient 로 밝 혀 지면 기본 직렬 화 체 제 는 이 필드 를 무시 합 니 다.(그리고 방법 은 writeObject 방법 을 사용자 정의 하 는 것 입 니 다.코드 예제 참조)
3.단일 클래스 에 readResolve()방법(단일 대상 으로 직접 돌아 가기)을 추가 하여 직렬 화 과정 에서 단일 특성 을 유지 하도록 합 니 다.
 
그리고 보충 해 주세요.
    경로 아래 jdk 에는 또 다른 형식의 대상 이 지속 된다.즉,외부 화(Externalization)이다.
public interface Externalizable extends java.io.Serializable {
  void writeExternal(ObjectOutput out) throws IOException;
  void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}

    외부 화 와 직렬 화 는 같은 목 표를 실현 하 는 두 가지 다른 방법 이다.
 
       Serializable 인 터 페 이 스 를 통 해 대상 의 서열 화 지원 은 jdk 에서 지원 합 니 다 API,그러나 자바.io.Externalizable 의 모든 실현 자 는 읽 기와 쓰기 의 구체 적 인 실현 을 제공 해 야 합 니 다.어떻게 실현 하 는 지 는 완전히 사용자 정의 입 니 다.직렬 화(Serializable) )필요 한 모든 정보(예 를 들 어 속성 및 속성 유형 등)를 자동 으로 저장 합 니 다.반 직렬 화 를 통 해 원래 와 같은 인 스 턴 스 로 만 들 고 외부 화(Externalizable)는 저 장 된 인 스 턴 스 에 필요 한 정보 만 저장 합 니 다.
예제 코드 는 다음 과 같다.
 
public class User implements Externalizable {
    private String name;
    transient private Integer age;  //     
    private Gender gender;

    public User() {
        System.out.println("none constructor");
    }

    public User(String name, Integer age, Gender gender) {
        System.out.println("arg constructor");
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    //     
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        out.writeInt(age);
        //   gender
    }
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        age = in.readInt();
    }

    //     
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(name);
        out.writeInt(age);
        //   gender
    }
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name = (String) in.readObject();
        age = in.readInt();
    } 
}

 Externalizable 로 직렬 화 합 니 다.대상 을 읽 을 때 직렬 화 된 클래스 의 무 참 구조 기 를 호출 하여 새로운 대상 을 만 든 다음 저 장 된 대상 의 필드 값 을 각각 새 대상 에 채 웁 니 다.Externalizable 인 터 페 이 스 를 실현 하 는 클래스 는 참여 하지 않 은 구조 기 를 제공 하고 접근 권한 은 Public 입 니 다.
 
        

좋은 웹페이지 즐겨찾기