InvalidClassException---Serializable 예제

5382 단어
오늘 프로젝트를 디버깅할 때 InvalidClassException 오류가 발생했습니다.디버깅을 통해 서버와 클라이언트 버전이 다르기 때문에 어떤 bean의 serialVersion UID가 다르다는 것을 알 수 있습니다.오늘 블로그를 갱신하고 대상의 서열화를 복습합시다.
객체를 서열화하려면 Serializable 인터페이스를 상속해야 합니다.하지만 Serializable 인터페이스에는 코드가 없습니다.이것은 jvm가 서열화 대상을 하기 전에 instanceof 판단을 먼저 하기 때문이다.
student 코드:
package codeTest;

import java.io.Serializable;

public class Student implements Serializable{

	private String name;
	private String passwd;
	private Node n;
	private String n1;
	public final String getName() {
		return name;
	}
	public final void setName(String name) {
		this.name = name;
	}
	public final String getPasswd() {
		return passwd;
	}
	public final void setPasswd(String passwd) {
		this.passwd = passwd;
	}
	public final Node getN() {
		return n;
	}
	public final void setN(Node n) {
		this.n = n;
	}
	public String toString(){
		return "name:"+this.name+"\t"+"passwds:"+this.passwd+"\t"+"node:"+this.n+"\r
"; } }

실행 코드
Student s = new Student();
		System.out.println(s instanceof Serializable);

결과는 true입니다.
 
이 학생류가 실례화될 수 있음을 나타낸다.
node 클래스:
package codeTest;

import java.io.Serializable;

public class Node implements Serializable{
	// , 
	private String name;  
	// 
	public String toString(){
		return " node2";
	}
}

주의해야 할 것은 우리가 학생을 서열화하려면 학생 안의 속성도 서열화 인터페이스, 예를 들어 node류를 실현하도록 해야 한다.
 
서열화는 무엇을 할 수 있습니까?일반적으로 원격 호출에 쓰인다.예를 들어 A 클라이언트가 B 서버 측에 클래스의 실례를 보내는 것은 클래스의 실례를 문자 흐름의 형식으로 서열화하여 네트워크를 통해 B 서버 측에 전송하는 것이다.서버 측에서 A가 보낸 흐름을 받아들인 다음에 이를 클래스로 강제로 전환하는 실례(물론 어떤 클래스를 보내려면 AB가 협상해야 한다.)
오늘의 테스트 애플릿은 원격 인터페이스 호출을 하지 않고, 오늘은 하나의 종류의 실례의 지속화만 테스트합니다.백점은 하나의 클래스를 실례화한 다음에 이 실례화된 클래스를 하나의 파일에 저장한 다음에 이 파일을 읽고 실례화된 클래스의 대상을 반서열화하여 복원하는 것이다.
student 클래스를 시리얼화하는 방법:
 
public static void outPut() {
		Student s = new Student();
		s.setName(" ");
		s.setPasswd("123123");
		Node d = new Node();
		s.setN(d);
		try {
			ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("d://test.txt"));
			output.writeObject(s);
			output.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

역정렬 방법:
 
 
 
public static void  inPut(){
		try {
			ObjectInputStream input = new ObjectInputStream(new FileInputStream("d://test.txt"));
			Student s1 = (Student)input.readObject();
			System.out.println(s1);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

서열화 방법을 실행하면 d디스크 아래에 테스트가 하나 더 있는 것을 볼 수 있습니다.txt 파일, 열면 모두 부호화됩니다.
 
시리얼화된 메서드를 실행한 결과:
name: 	passwds:123123	node: node2

이를 통해 알 수 있듯이 반서열화 방법은 서열화로 받은 파일을 해석해 냈다.우리가 구체적인 대상을 만들어 전송하거나 저장하려고 할 때, 이런 서열화된 형식을 사용할 수 있다.
 
위의student클래스에 버전번호serialVersionUID가 지정되지 않으면 jvm에서 서열화할 때 기본적으로 버전번호serialVersionUID를 생성하고 반서열화할 때 이 버전번호에 따라 교정하며 대응하지 않으면 글에서 언급한 오류인validClassException을 던집니다.serialVersionUID와 파일의 유형, 이름, 속성, 방법이 모두 관련되어 있습니다.예를 들어 제가 학생에 임의의 방법이나 속성을 넣으면 오류가 발생합니다.
java.io.InvalidClassException: codeTest.Student; local class incompatible: stream classdesc serialVersionUID = 2222222222222222222, local class serialVersionUID = 222221222222222222
	at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:560)
	at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1582)
	at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
	at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
	at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
	at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
	at codeTest.serialVersionTest.inPut(serialVersionTest.java:48)
	at codeTest.serialVersionTest.main(serialVersionTest.java:22)

그러나 많은 경우에 우리는 구 버전을 호환하기를 원하기 때문에 serialVersionUID 속성을 사용해야 한다.student에 private static final long serialVersion UID 값을 추가하면 임의로 지정할 수 있습니다.이때 SerialVersionUID의 값이 변하지 않으면 아무리 학생t의 다른 속성을 수정해도 (node의 SerialVersionUID도 변하지 않는다) 학생t의 다른 속성을 모두 삭제하고
package codeTest;

import java.io.Serializable;

public class Student implements Serializable{
	/**  
	* @Fields serialVersionUID : TODO( )  
	*/  
	private static final long serialVersionUID = 222122222222222L;
	
}

역서열화 방법을 실행한 결과는 다음과 같습니다.
codeTest.Student@768965fb

호환성이 너무 강해요.
서열화된 부분도 업데이트를 원한다면 버전 번호만 바꾸면 된다.

좋은 웹페이지 즐겨찾기