JAVA 의 직렬 화 와 transient 키워드

11900 단어 자바
1. 자바 직렬 화 자바 는 대상 의 직렬 화 체 제 를 제공 합 니 다. 이 메커니즘 에서 한 대상 은 하나의 바이트 서열 로 표시 할 수 있 습 니 다. 이 바이트 서열 은 이 대상 의 데이터, 대상 의 유형 에 대한 정보 와 대상 에 저 장 된 데이터 의 유형 을 포함 합 니 다.
직렬 화 대상 을 파일 에 기록 한 후 파일 에서 읽 어 내 고 역 직렬 화 할 수 있 습 니 다. 즉, 대상 의 유형 정보, 대상 의 데이터, 그리고 대상 의 데이터 형식 은 메모리 에 새 대상 을 만 드 는 데 사용 할 수 있 습 니 다.
전체 과정 은 자바 가상 머 신 (JVM) 이 독립 된 것 이다. 즉, 한 플랫폼 에서 서열 화 된 대상 은 다른 완전히 다른 플랫폼 에서 이 대상 을 반 서열 화 할 수 있다.
클래스 Object InputStream 과 Object OutputStream 은 고 차원 의 데이터 흐름 으로 반 직렬 화 와 직렬 화 대상 을 포함 하 는 방법 입 니 다.
Object OutputStream 류 는 여러 가지 데이터 형식 을 쓰 는 방법 을 포함 하지만 특별한 방법 은 예외 입 니 다.
public final void writeObject(Object x) throws IOException

위의 방법 은 대상 을 정렬 하여 출력 흐름 으로 보 냅 니 다.비슷 한 Object InputStream 클래스 는 다음 과 같은 반 직렬 화 대상 을 포함 하 는 방법 입 니 다.
public final Object readObject() throws IOException, 
                                 ClassNotFoundException

이 방법 은 흐름 에서 다음 대상 을 꺼 내 대상 을 역 직렬 화 시킨다.그것 의 반환 값 은 Object 이기 때문에 적당 한 데이터 형식 으로 변환 해 야 합 니 다.
자바 에서 어떻게 작 동 하 는 지 보 여주 기 위해 저 는 이전 튜 토리 얼 에서 언급 한 User 류 를 사용 할 것 입 니 다. 다음 과 같은 User 류 를 정의 했다 고 가정 하면 Serializable 인 터 페 이 스 를 실현 할 것 입 니 다.
public class User implements java.io.Serializable
{
   public String name;
   public String address;
   public transient String  passWord;
   public int number;

   .....

public static void main(String[] args) {
       User u = new User();
       u.setName("IT   ");
       u.setPassWord("123456");
       u.setNumber(1264064998);
       u.setAddress("XXXXX");
       System.out.println("     -->  :"+u.getName()+"     :"+u.getPassWord());
       try {
        FileOutputStream fs = new FileOutputStream("/home/xjb/text.txt");
        ObjectOutputStream os = new ObjectOutputStream(fs);
        os.writeObject(u);
        os.flush();
        os.close();

        FileInputStream fi = new FileInputStream("/home/xjb/text.txt");
        ObjectInputStream is = new ObjectInputStream(fi);
        u  = (User) is.readObject();
        is.close();
        System.out.println("      -->  :"+u.getName()+"     :"+u.getPassWord());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
   }
}

실행 결과:
     -->  :IT        :123456
      -->  :IT        :null

주의: (1), 한 유형의 대상 이 직렬 화 에 성공 하려 면 두 가지 조건 을 만족 시 켜 야 합 니 다. 이 종 류 는 자바. io. Serializable 대상 을 실현 해 야 합 니 다.이 종류의 모든 속성 은 반드시 직렬 화 되 어야 한다.만약 하나의 속성 이 직렬 화 되 지 않 는 다 면, 이 속성 은 키워드 transient 를 사용 하여 짧 은 것 임 을 표시 해 야 합 니 다.(2), readObject () 방법 중의 try / catch 코드 블록 은 ClassNotFoundException 이상 을 캡 처 하려 고 시도 합 니 다.JVM 의 역 직렬 화 대상 은 바이트 코드 를 찾 을 수 있 는 클래스 여야 합 니 다.JVM 이 역 직렬 화 대상 을 찾 는 과정 에서 이 종 류 를 찾 지 못 하면 ClassNotFoundException 이상 을 던 집 니 다.여기 서 readObject () 방법의 반환 값 은 User 참조 로 바 뀌 었 습 니 다. 대상 이 직렬 화 되 었 을 때 속성 passWord 의 값 은 123456 이지 만 이 속성 은 짧 기 때문에 출력 흐름 에 전송 되 지 않 았 습 니 다.그래서 역 직렬 화 된 사용자 대상 의 passWord 속성 은 null 입 니 다.
2. 키워드 transient 는 실제 개발 과정 에서 우 리 는 이런 문제 에 자주 부 딪 힌 다. 이런 유형의 일부 속성 은 직렬 화 되 어야 하고 다른 속성 은 직렬 화 되 지 않 아 도 된다. 예 를 들 어 한 사용자 가 민감 한 정보 (예 를 들 어 비밀번호, 은행 카드 번호 등) 가 있 으 면 안전 을 위해 네트워크 에서 조작 하 는 것 을 원 하지 않 는 다.(주로 직렬 화 작업 과 관련 되 며, 로 컬 직렬 화 캐 시 도 적 용 됩 니 다) 에서 전 송 됩 니 다. 이 정보 에 대응 하 는 변 수 는 transient 키 워드 를 추가 할 수 있 습 니 다. 다시 말 하면 이 필드 의 생명 주 기 는 호출 자의 메모리 에 만 저장 되 며, 디스크 에 기록 되 지 않 습 니 다. 즉, 위 에서 언급 한 짧 은 것 입 니 다. (1)변수 가 transient 에 의 해 수식 되면 변 수 는 더 이상 대상 의 지속 적 인 일부분 이 아니 라 이 변수 내용 은 직렬 화 된 후에 접근 할 수 없습니다.
(2) transient 키 워드 는 변 수 를 수식 할 수 있 을 뿐 방법 과 클래스 를 수식 할 수 없습니다. 로 컬 변 수 는 transient 키워드 로 수식 할 수 없습니다. 변 수 는 사용자 정의 클래스 변수 라면 Serializable 인 터 페 이 스 를 실현 해 야 합 니 다.
(3) transient 키워드 에 의 해 수 식 된 변 수 는 더 이상 직렬 화 되 지 않 습 니 다. 정적 변 수 는 transient 에 의 해 수식 되 든 안 되 든 직렬 화 되 지 않 습 니 다.
세 번 째 는 약간 혼 란 스 러 울 수 있 습 니 다. User 클래스 의 name 필드 에 static 키 워드 를 추가 한 후에 도 프로그램 실행 결 과 는 변 하지 않 습 니 다. 즉, static 유형의 name 도 [IT 농민 공] 으로 읽 었 습 니 다. 이것 은 세 번 째 와 모순 되 지 않 습 니까? 사실은 이 렇 습 니 다. 세 번 째 는 확실 합 니 다. (정적 변 수 는 transient 에 의 해 수식 되 든 안 되 든 직렬 화 되 지 않 습 니 다)역 직렬 화 후 클래스 에서 static 형 변수 name 의 값 은 현재 JVM 에서 static 변수 에 대응 하 는 값 입 니 다. 이 값 은 JVM 에서 역 직렬 화 된 것 이 아 닙 니 다.
public class User implements java.io.Serializable
{
   private static String name;
   private String address;
   private transient String  passWord;
   private int number;
  ...

public static void main(String[] args) {
       User u = new User();
       u.setName("admin");
       u.setPassWord("IT   ");
       u.setNumber(1264064998);
       u.setAddress("XXXXX");
       System.out.println("     -->  :"+u.getName()+"     :"+u.getPassWord());
       try {
        FileOutputStream fs = new FileOutputStream("/home/xjb/text.txt");
        ObjectOutputStream os = new ObjectOutputStream(fs);
        os.writeObject(u);
        os.flush();
        os.close();

        //      
        User.name="IT   Test";
        FileInputStream fi = new FileInputStream("/home/xjb/text.txt");
        ObjectInputStream is = new ObjectInputStream(fi);
        u  = (User) is.readObject();
        is.close();
        System.out.println("      -->  :"+u.getName()+"     :"+u.getPassWord());
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
   }
}

실행 결과:
     -->  :IT        :123456
      -->  :IT   Test     :null

이 는 역 직렬 화 후 클래스 에서 static 형 변수 name 의 값 이 현재 JVM 에서 static 변수 에 대응 하 는 값 이 고 수정 후 [IT 농민 공 Test] 가 아니 라 직렬 화 된 값 [IT 농민 공] 임 을 나타 낸다.
메모: transient 키워드 에 의 해 수 정 된 변 수 는 정말 직렬 화 될 수 없 습 니까?
public class ExternalizableTest implements Externalizable{
     private transient String text = "         ?";
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(text);

        }
        @Override
        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            text = (String) in.readObject();
        }

        public static void main(String[] args) {
            try {
            ExternalizableTest test = new ExternalizableTest();
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream(new File("/home/xjb/text.txt")));
            out.writeObject(test);

            ObjectInput in = new ObjectInputStream(new FileInputStream(new File("/home/xjb/text.txt")));
            test = (ExternalizableTest) in.readObject();
            System.out.println(test.text);

            out.close();
            in.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
}

실행 결과:

자바 에 서 는 대상 의 직렬 화 는 두 가지 인 터 페 이 스 를 통 해 이 루어 질 수 있 기 때문에 Serializable 인 터 페 이 스 를 실현 하면 모든 직렬 화 는 자동 으로 이 루어 집 니 다. Externalizable 인 터 페 이 스 를 실현 하면 자동 으로 직렬 화 할 수 있 는 것 이 아무것도 없습니다. writeExternal 방법 에서 정렬 할 변 수 를 수 동 으로 지정 해 야 합 니 다. 이것 은 transient 에 의 해 수식 되 지 않 았 는 지 여부 와 같 습 니 다.닫 습 니 다. 따라서 두 번 째 예 는 null 이 아 닌 변수 text 가 초기 화 된 내용 을 출력 합 니 다.
참조 출처: 초보 튜 토리 얼 자바 transient 키워드 사용 팁

좋은 웹페이지 즐겨찾기