[java] 직렬화 가능이란 무엇입니까?

클래스가 SerializableJava 로 존재한다는 것은 정확히 무엇을 의미 합니까? 또는 일반적으로 그 문제에 대해 …



답변

직렬화 는 예를 들어 디스크에 저장하기 위해 메모리에서 일련의 비트로 객체를 유지합니다. 역 직렬화는 반대입니다. 디스크에서 데이터를 읽어 객체를 수화 / 생성합니다.

질문의 맥락에서 클래스에서 구현되는 경우이 클래스는 다른 직렬 변환기에 의해 자동으로 직렬화 및 직렬화 해제 될 수있는 인터페이스입니다.


답변

대부분의 사용자가 이미 답변을했지만 아이디어를 설명하기 위해 필요한 사람들을위한 예를 추가하고 싶습니다.

다음과 같은 클래스 사람이 있다고 가정 해 봅시다.

public class Person implements java.io.Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    public String firstName;
    public String lastName;
    public int age;
    public String address;

    public void play() {
        System.out.println(String.format(
                "If I win, send me the trophy to this address: %s", address));
    }
    @Override
    public String toString() {
        return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName);
    }
}

그런 다음 다음과 같은 객체를 만듭니다.

Person william = new Person();
        william.firstName = "William";
        william.lastName = "Kinaan";
        william.age = 26;
        william.address = "Lisbon, Portugal";

해당 개체를 여러 스트림으로 직렬화 할 수 있습니다. 나는 두 가지 흐름으로 그렇게 할 것입니다.

표준 출력으로 직렬화 :

public static void serializeToStandardOutput(Person person)
            throws IOException {
        OutputStream outStream = System.out;
        ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
        stdObjectOut.writeObject(person);
        stdObjectOut.close();
        outStream.close();
    }

파일로 직렬화 :

public static void serializeToFile(Person person) throws IOException {
        OutputStream outStream = new FileOutputStream("person.ser");
        ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream);
        fileObjectOut.writeObject(person);
        fileObjectOut.close();
        outStream.close();
    }

그때:

파일에서 역 직렬화 :

public static void deserializeFromFile() throws IOException,
            ClassNotFoundException {
        InputStream inStream = new FileInputStream("person.ser");
        ObjectInputStream fileObjectIn = new ObjectInputStream(inStream);
        Person person = (Person) fileObjectIn.readObject();
        System.out.println(person);
        fileObjectIn.close();
        inStream.close();
    }


답변

즉, 클래스의 인스턴스를 바이트 스트림으로 변환 한 다음 (예 : 파일로 저장) 다시 클래스로 변환 할 수 있습니다. 이 리로딩은 프로그램의 다른 인스턴스 또는 다른 머신에서도 발생할 수 있습니다. 직렬화 (어떤 언어로든)는 특히 모든 직렬화 가능한 개체 내의 다른 개체에 대한 참조가있는 경우 모든 종류의 문제를 포함합니다.


답변

다음은 Serialization에 대한 자세한 설명입니다 . (나의 블로그)

직렬화 :

직렬화는 객체의 상태를 직렬화하는 프로세스로, 일련의 바이트 형식으로 표시되고 저장됩니다. 파일에 저장할 수 있습니다. 파일에서 객체의 상태를 읽고 복원하는 과정을 역 직렬화라고합니다.

직렬화의 필요성은 무엇입니까?

현대 건축에서는 항상 객체 상태를 저장 한 다음 검색해야합니다. 예를 들어, 최대 절전 모드에서 객체를 저장하려면 클래스를 Serializable로 만들어야합니다. 그것은 일단 객체 상태가 바이트 형태로 저장되면 다른 시스템으로 전송되어 상태에서 읽고 클래스를 검색 할 수 있다는 것입니다. 객체 상태는 데이터베이스 또는 다른 jvm 또는 별도의 구성 요소에서 올 수 있습니다. Serialization의 도움으로 Object 상태를 검색 할 수 있습니다.

코드 예 및 설명 :

먼저 아이템 클래스를 보자 :

public class Item implements Serializable{

    /**
    *  This is the Serializable class
    */
    private static final long serialVersionUID = 475918891428093041L;
    private Long itemId;
    private String itemName;
    private transient Double itemCostPrice;
    public Item(Long itemId, String itemName, Double itemCostPrice) {
        super();
        this.itemId = itemId;
        this.itemName = itemName;
        this.itemCostPrice = itemCostPrice;
      }

      public Long getItemId() {
          return itemId;
      }

     @Override
      public String toString() {
          return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
       }


       public void setItemId(Long itemId) {
           this.itemId = itemId;
       }

       public String getItemName() {
           return itemName;
       }
       public void setItemName(String itemName) {
            this.itemName = itemName;
        }

       public Double getItemCostPrice() {
            return itemCostPrice;
        }

        public void setItemCostPrice(Double itemCostPrice) {
             this.itemCostPrice = itemCostPrice;
        }
}

위 코드에서 Item 클래스가 Serializable을 구현 하고 있음을 알 수 있습니다 .

클래스를 직렬화 할 수있는 인터페이스입니다.

이제 serialVersionUID 라는 변수가 Long 변수로 초기화 된 것을 볼 수 있습니다 . 이 숫자는 클래스 상태 및 클래스 속성에 따라 컴파일러에서 계산됩니다. 파일에서 객체의 상태를 읽을 때 jvm이 객체의 상태를 식별하는 데 도움이되는 숫자입니다.

이를 위해 공식 Oracle Documentation을 살펴볼 수 있습니다.

직렬화 런타임은 직렬화 가능 오브젝트의 송신자 및 수신자가 직렬화와 호환되는 해당 오브젝트에 대해 클래스를로드했는지 검증하기 위해 직렬화 해제 중에 사용되는 직렬 버전 UID라고하는 버전 번호를 각 직렬화 가능 클래스와 연관시킵니다. 수신자가 해당 발신자의 클래스와 다른 serialVersionUID를 가진 객체의 클래스를로드 한 경우 역 직렬화는 InvalidClassException을 발생시킵니다. 직렬화 가능 클래스는 static, final 및 long 유형이어야하는 “serialVersionUID”라는 필드를 선언하여 고유 한 serialVersionUID를 명시 적으로 선언 할 수 있습니다. ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; 직렬화 가능 클래스가 serialVersionUID를 명시 적으로 선언하지 않으면 직렬화 런타임은 Java (TM) 객체 직렬화 스펙에 설명 된대로 클래스의 다양한 측면을 기반으로 해당 클래스의 기본 serialVersionUID 값을 계산합니다. 그러나 기본 serialVersionUID 계산은 컴파일러 구현에 따라 달라질 수있는 클래스 세부 정보에 매우 민감하므로 역 직렬화 중에 예기치 않은 InvalidClassExceptions가 발생할 수 있으므로 모든 serializable 클래스는 serialVersionUID 값을 명시 적으로 선언하는 것이 좋습니다. 따라서 다른 Java 컴파일러 구현에서 일관된 serialVersionUID 값을 보장하려면 직렬화 가능 클래스가 명시 적 serialVersionUID 값을 선언해야합니다. 또한 명시적인 serialVersionUID 선언은 가능한 경우 전용 수정자를 사용하는 것이 좋습니다.

만약 당신이 우리가 사용한 다른 키워드가 transient 인 것을 눈치 채 셨다면 .

필드를 직렬화 할 수없는 경우 일시적으로 표시해야합니다. 여기서 itemCostPrice 를 일시적으로 표시하고 파일에 쓰지 않기를 원합니다.

이제 파일에 객체의 상태를 작성하고 거기서 읽는 방법을 살펴 보겠습니다.

public class SerializationExample {

    public static void main(String[] args){
        serialize();
       deserialize();
    }

    public static void serialize(){

         Item item = new Item(1L,"Pen", 12.55);
         System.out.println("Before Serialization" + item);

         FileOutputStream fileOut;
         try {
             fileOut = new FileOutputStream("/tmp/item.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut);
             out.writeObject(item);
             out.close();
             fileOut.close();
             System.out.println("Serialized data is saved in /tmp/item.ser");
           } catch (FileNotFoundException e) {

                  e.printStackTrace();
           } catch (IOException e) {

                  e.printStackTrace();
           }
      }

    public static void deserialize(){
        Item item;

        try {
                FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn);
                item = (Item) in.readObject();
                System.out.println("Serialized data is read from /tmp/item.ser");
                System.out.println("After Deserialization" + item);
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        } catch (ClassNotFoundException e) {
               e.printStackTrace();
        }
     }
}

위에서 우리는 객체의 직렬화와 역 직렬화의 예를 볼 수 있습니다.

이를 위해 두 가지 클래스를 사용했습니다. 객체를 직렬화하기 위해 ObjectOutputStream을 사용했습니다. writeObject 메소드를 사용하여 파일에 오브젝트를 작성했습니다.

역 직렬화를 위해 파일에서 객체를 읽는 ObjectInputStream을 사용했습니다. readObject를 사용하여 파일에서 오브젝트 데이터를 읽습니다.

위 코드의 출력은 다음과 같습니다.

Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]

공지 사항 것을 itemCostPrice 직렬화 된 객체는 널 (null) 이 작성되지 않았습니다으로가.


답변

직렬화에는 객체의 현재 상태를 스트림에 저장하고 해당 스트림에서 동등한 객체를 복원하는 작업이 포함됩니다. 스트림은 객체의 컨테이너로 기능합니다


답변

직렬화 가능은 인터페이스처럼 호출되지만 런타임시 직렬화 서브 시스템에 대한 플래그와 유사합니다. 이 개체를 저장할 수 있다고 말합니다. 직렬화 가능한 객체 및 휘발성으로 표시된 객체를 제외한 모든 객체 인스턴스 변수가 저장됩니다.

외부 설정을 유지하지 않고도 응용 프로그램에서 색상을 옵션으로 변경할 수 있다고 상상할 때마다 색상을 실행할 때마다 색상을 변경해야합니다.


답변

직렬화는 객체와 데이터를 파일에 저장하거나 쓰는 기술입니다. ObjectOutputStreamFileOutputStream클래스 를 사용 합니다. 이 클래스에는 객체를 유지하기위한 특정 메소드가 있습니다. 처럼writeObject();

수치와 명확한 explantaion. 자세한 내용은 여기를 참조하십시오