transient 키워드 요약

7393 단어
transient 키워드를 소개하기 전에 먼저 대상의 서열화를 알아야 한다. 하나의 클래스가 Serializable 인터페이스를 실현하면 우리는 그것을 메모리에 쓰고 메모리에서 읽어서 원래와 똑같은 대상으로 조립할 수 있다.
  • transient의 역할 및 사용 방법

    transient 키워드는 구성원 변수(방법일 수 없음)를 수식하는 데 사용되며, 이 변수가 서열화되는 것을 방지한다. 예를 들어 숨겨야 할 정보(예를 들어 비밀번호 등)가 안전을 위해 서열화되고 지속되는 것을 피하기 위해서는 이때transient 키워드로 수식해야 한다.한 마디로 하면java의transient 키워드는 우리에게 편리함을 제공합니다. 당신은serilizable 인터페이스를 실현하기만 하면 서열화된 속성이 필요하지 않은 앞에 키워드transient를 추가하고 서열화된 대상을 추가할 때 이 속성은 지정된 목적지에 서열화되지 않습니다.
  • package blog;
    
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.io.Serializable;
    
    public class user implements Serializable{
        private String username;
        transient private String password;
        public user(String username,String password) {
            this.username=username;
            this.password=password;
                    
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    public class serilizable {
        
        public static void main(String[] args) {
            user U=new user(" ","caixukun");
            try {
                ObjectOutputStream out= new ObjectOutputStream(new FileOutputStream("C:\\Users\\Administrator\\Desktop\\user.txt"));
                out.writeObject(U);
                out.flush();
                out.close();
                ObjectInputStream in=new ObjectInputStream(new FileInputStream("C:\\Users\\Administrator\\Desktop\\user.txt"));
                user o=(user)in.readObject();
                in.close();
                System.out.println(o.getUsername());// : 
                System.out.println(o.getPassword());// :null
                
            } catch (Exception e) {
                // TODO   catch  
                e.printStackTrace();
            }
        }
    
    }
    

    위의 결과를 통해 알 수 있듯이transient 키워드로 수식된 변수는 반서열화될 때 읽을 수 없기 때문에 일부 정보의 안전성을 확보할 수 있다.
  • transient 사용 매듭


  • 1) 변수가transient에 수식되면 변수는 더 이상 대상의 지속화의 일부분이 아니며 이 변수의 내용은 서열화된 후에 접근할 수 없습니다.
    2)transient 키워드는 변수만 수식할 수 있고 방법과 클래스는 수식할 수 없습니다.로컬 변수는transient 키워드에 의해 수식될 수 없습니다.변수가 사용자 정의 클래스 변수라면, 이 클래스는serializable 인터페이스를 실현해야 합니다.
    3) 정적 (static) 변수는transient에 의해 수식되었든 안 되었든 서열화될 수 없습니다.(정적 변수의 실제 저장 원리와 결합)
  • transient 사용 디테일 - transient 키워드로 장식된 변수는 정말 서열화될 수 없습니까?


  • 사실상 이 말은 단편적이다. 전제 조건은 이 종류가serilizable 인터페이스를 실현했다는 것이다. (모든 서열화는 자동으로 진행될 것이다.)자바에서 서열화를 실현하는 방법은 한 가지가 아니라 Externalizable 인터페이스도 있다. 이 인터페이스는 어떠한 변수의 자동 서열화도 실현하지 않고 모든 변수의 서열화는 대응하는 writeExternal 방법에서 수동으로 지정해야 한다. 이것은transient에 의해 수식되었는지와 무관하다.예:
    import java.io.Externalizable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    
    /**
     * @descripiton Externalizable 
     * 
     * @author Alexia
     * @date 2013-10-15
     *
     */
    public class ExternalizableTest implements Externalizable {
    
        private transient String content = " , , transient ";
    
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(content);// 
        }
    
        @Override
        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            content = (String) in.readObject();// 
        }
    
        public static void main(String[] args) throws Exception {
            
            ExternalizableTest et = new ExternalizableTest();
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                    new File("test")));
            out.writeObject(et);
    
            ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                    "test")));
            et = (ExternalizableTest) in.readObject();
            System.out.println(et.content);
    
            out.close();
            in.close();
        }
    }
    

    서열화 지식 확장


    readResolve() 메서드와 Serilizable 인터페이스
    한 가지 문제를 생각하면, 서열화와 반서열화는 단례 모델을 파괴하지 않을까?단일 예는 하나의 JVM에 하나의 클래스 대상이 있어야 하는데, 지금은 반서열화를 통해 새로운 대상이 복제되었다.
    public class mysingleton implements Serializable {
        
        private String message;
     private static final mysingleton instance=new mysingleton(" ");
     public mysingleton(String string) {
            // TODO  
            this.message=string;
        }
    public static mysingleton getInstance() {
        return instance;
    }
    

    mysingleton 대상 (getInstance 방법으로 얻은 그 단일 대상) 을 서열화한 후 메모리에서 읽을 때, 새롭지만 원래와 같은 mysingleton 대상이 존재합니다.그러면 어떻게 일례 모드를 유지합니까?이것은readResolve 방법을 사용해야 합니다.다음과 같습니다.
    public final class MySingleton implements Serializable{ 
      private MySingleton() { } 
      private static final MySingleton INSTANCE = new MySingleton(); 
      public static MySingleton getInstance() { return INSTANCE; } 
      private Object readResolve() throws ObjectStreamException { 
        // instead of the object we're on, 
        // return the class variable INSTANCE 
       return INSTANCE; 
      } 
    } 
    

    jdk의serilizable 인터페이스 설명


    대상을 흐름에 쓸 때 사용할 대체 대상의 정렬 가능한 클래스를 지정해야 합니다: Object write Replace () throws Object Stream Exception.만약 이 방법이 존재하고 서열화된 대상의 클래스에 정의된 방법으로 접근할 수 있다면, 이 writeReplace 방법은 서열화를 통해 호출됩니다.따라서 이 방법은 사유, 보호, 사유 방문을 할 수 있다.하위 클래스 접근 이 방법은 자바 접근 가능한 규칙을 따릅니다.
    흐름에서 실례를 읽을 때 교체된 클래스를 지정해야 하며, 정확한 서명을 가진 특수한 방법을 실현해야 한다.Object readResolve() throws ObjectStreamException; 이 readResolve 방법은 writeReplace와 같은 호출 규칙과 접근 가능한 규칙을 따른다.
    서열화 실행 시 모든 서열화 가능한 클래스를serialVersionUID라는 버전 번호와 연결합니다. 이 서열 번호는 반서열화 기간에 서열화 대상의 발송자와 수신자가 이 서열화와 호환되는 대상의 클래스를 불러왔는지 확인하는 데 사용됩니다.수신자가 해당 발송 인간과 다른 serialVersionUID의 대상을 가진 클래스를 불러오면 반서열화InvalidClassException가 발생한다.하나의 서열화된 클래스는 "serialVersionUID"라는 필드를 성명함으로써 자신의 SerialVersion UID를 현시적으로 성명할 수 있다. 이 필드는 정적이어야 한다. 최종적으로 유형은 long이다. static final long serialVersion UID = 42L;
    시리얼화된 클래스에 SerialVersionUID가 명시되어 있지 않으면 시리얼화된 실행 시 자바(TM) 대상의 시리얼화 규범에 기술된 클래스의 각 방면에 따라 이 클래스의 기본 시리얼VersionUID 값을 계산합니다.그러나 모든 서열화된 클래스는 SerialVersionUID 값을 명확하게 설명하는 것을 강력히 권장합니다. 기본적인 SerialVersionUID 계산은 클래스의 상세한 정보에 민감하기 때문에 컴파일러의 구현에 따라 다르기 때문에 반InvalidClassException화 기간InvalidClassException의 InvalidClassException을 초래할 수 있습니다.따라서 서로 다른 자바 컴파일러 간의 일치된 serialVersionUID 값을 확보하기 위해서, 서열화된 클래스는 현식의 serialVersionUID 값을 성명해야 한다.또한 명시적인 SerialVersionUID 성명은 가능한 한 private 수식자를 사용해야 한다. 왜냐하면 이런 성명은 즉각 성명된 클래스인 SerialVersionUID 필드에만 적용되기 때문에 계승 구성원으로서 무효이기 때문이다.그룹 클래스는 명시적인 SerialVersionUID를 성명할 수 없기 때문에 항상 기본적인 계산 값을 가지고 있지만, 그룹 클래스에 대해서는 SerialVersionUID 값과 일치하는 요구를 포기합니다.

    엔딩


    자바 서열화에 심각한 안전성 문제가 존재하기 때문에 실제 개발 과정에서 대체 방안을 우선적으로 고려한다. 예를 들어 크로스플랫폼 구조화 데이터(JSON과Protocol Buffers)를 우선적으로 고려한다.

    serilizable 인터페이스 조심스럽게 사용하기


    Serializable 인터페이스를 실현하는 주요 대가는 클래스의 실현이 발표되면 클래스를 변경하는 유연성을 떨어뜨리는 것이다.Serializable 인터페이스를 실현하는 두 번째 대가는 버그와 보안 빈틈이 발생할 가능성을 증가시켰다는 것이다.Serializable 인터페이스를 실현하는 세 번째 대가는 발표 클래스의 새로운 버전과 관련된 테스트 부담을 증가시켰다는 것이다.내부 클래스는 Serializable을 실현해서는 안 된다.

    좋은 웹페이지 즐겨찾기